VirtualBox

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

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

VMM/HM: Separate interrupt and exception injected stats.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 721.7 KB
Line 
1/* $Id: HMVMXR0.cpp 83025 2020-02-07 18:00:45Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef 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 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
866 * @returns @c true if it's part of LBR stack, @c false otherwise.
867 *
868 * @param pVM The cross context VM structure.
869 * @param idMsr The MSR.
870 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
871 * Optional, can be NULL.
872 *
873 * @remarks Must only be called when LBR is enabled.
874 */
875DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
876{
877 Assert(pVM->hm.s.vmx.fLbr);
878 Assert(pVM->hm.s.vmx.idLbrFromIpMsrFirst);
879 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
880 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrFromIpMsrFirst;
881 if (idxMsr < cLbrStack)
882 {
883 if (pidxMsr)
884 *pidxMsr = idxMsr;
885 return true;
886 }
887 return false;
888}
889
890
891/**
892 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
893 * @returns @c true if it's part of LBR stack, @c false otherwise.
894 *
895 * @param pVM The cross context VM structure.
896 * @param idMsr The MSR.
897 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
898 * Optional, can be NULL.
899 *
900 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
901 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
902 */
903DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
904{
905 Assert(pVM->hm.s.vmx.fLbr);
906 if (pVM->hm.s.vmx.idLbrToIpMsrFirst)
907 {
908 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrToIpMsrLast - pVM->hm.s.vmx.idLbrToIpMsrFirst + 1;
909 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrToIpMsrFirst;
910 if (idxMsr < cLbrStack)
911 {
912 if (pidxMsr)
913 *pidxMsr = idxMsr;
914 return true;
915 }
916 }
917 return false;
918}
919
920
921/**
922 * Gets the CR0 guest/host mask.
923 *
924 * These bits typically does not change through the lifetime of a VM. Any bit set in
925 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
926 * by the guest.
927 *
928 * @returns The CR0 guest/host mask.
929 * @param pVCpu The cross context virtual CPU structure.
930 */
931static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
932{
933 /*
934 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
935 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
936 *
937 * Furthermore, modifications to any bits that are reserved/unspecified currently
938 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
939 * when future CPUs specify and use currently reserved/unspecified bits.
940 */
941 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
942 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
943 * and @bugref{6944}. */
944 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
945 return ( X86_CR0_PE
946 | X86_CR0_NE
947 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
948 | X86_CR0_PG
949 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
950}
951
952
953/**
954 * Gets the CR4 guest/host mask.
955 *
956 * These bits typically does not change through the lifetime of a VM. Any bit set in
957 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
958 * by the guest.
959 *
960 * @returns The CR4 guest/host mask.
961 * @param pVCpu The cross context virtual CPU structure.
962 */
963static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
964{
965 /*
966 * We construct a mask of all CR4 bits that the guest can modify without causing
967 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
968 * a VM-exit when the guest attempts to modify them when executing using
969 * hardware-assisted VMX.
970 *
971 * When a feature is not exposed to the guest (and may be present on the host),
972 * we want to intercept guest modifications to the bit so we can emulate proper
973 * behavior (e.g., #GP).
974 *
975 * Furthermore, only modifications to those bits that don't require immediate
976 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
977 * depends on CR3 which might not always be the guest value while executing
978 * using hardware-assisted VMX.
979 */
980 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
981 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
982 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
983 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
984
985 /*
986 * Paranoia.
987 * Ensure features exposed to the guest are present on the host.
988 */
989 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
990 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
991 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
992
993 uint64_t const fGstMask = ( X86_CR4_PVI
994 | X86_CR4_TSD
995 | X86_CR4_DE
996 | X86_CR4_MCE
997 | X86_CR4_PCE
998 | X86_CR4_OSXMMEEXCPT
999 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1000 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1001 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1002 return ~fGstMask;
1003}
1004
1005
1006/**
1007 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
1008 * area.
1009 *
1010 * @returns @c true if it's different, @c false otherwise.
1011 * @param pVmcsInfo The VMCS info. object.
1012 */
1013DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1014{
1015 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1016 && pVmcsInfo->pvGuestMsrStore);
1017}
1018
1019
1020/**
1021 * Sets the given Processor-based VM-execution controls.
1022 *
1023 * @param pVmxTransient The VMX-transient structure.
1024 * @param uProcCtls The Processor-based VM-execution controls to set.
1025 */
1026static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1027{
1028 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1029 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1030 {
1031 pVmcsInfo->u32ProcCtls |= uProcCtls;
1032 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1033 AssertRC(rc);
1034 }
1035}
1036
1037
1038/**
1039 * Removes the given Processor-based VM-execution controls.
1040 *
1041 * @param pVCpu The cross context virtual CPU structure.
1042 * @param pVmxTransient The VMX-transient structure.
1043 * @param uProcCtls The Processor-based VM-execution controls to remove.
1044 *
1045 * @remarks When executing a nested-guest, this will not remove any of the specified
1046 * controls if the nested hypervisor has set any one of them.
1047 */
1048static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1049{
1050 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1051 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1052 {
1053#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1054 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
1055 ? true
1056 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1057#else
1058 NOREF(pVCpu);
1059 bool const fRemoveCtls = true;
1060#endif
1061 if (fRemoveCtls)
1062 {
1063 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1064 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1065 AssertRC(rc);
1066 }
1067 }
1068}
1069
1070
1071/**
1072 * Sets the TSC offset for the current VMCS.
1073 *
1074 * @param uTscOffset The TSC offset to set.
1075 * @param pVmcsInfo The VMCS info. object.
1076 */
1077static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1078{
1079 if (pVmcsInfo->u64TscOffset != uTscOffset)
1080 {
1081 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1082 AssertRC(rc);
1083 pVmcsInfo->u64TscOffset = uTscOffset;
1084 }
1085}
1086
1087
1088/**
1089 * Adds one or more exceptions to the exception bitmap and commits it to the current
1090 * VMCS.
1091 *
1092 * @param pVmxTransient The VMX-transient structure.
1093 * @param uXcptMask The exception(s) to add.
1094 */
1095static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1096{
1097 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1098 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1099 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1100 {
1101 uXcptBitmap |= uXcptMask;
1102 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1103 AssertRC(rc);
1104 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1105 }
1106}
1107
1108
1109/**
1110 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1111 *
1112 * @param pVmxTransient The VMX-transient structure.
1113 * @param uXcpt The exception to add.
1114 */
1115static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1116{
1117 Assert(uXcpt <= X86_XCPT_LAST);
1118 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1119}
1120
1121
1122/**
1123 * Remove one or more exceptions from the exception bitmap and commits it to the
1124 * current VMCS.
1125 *
1126 * This takes care of not removing the exception intercept if a nested-guest
1127 * requires the exception to be intercepted.
1128 *
1129 * @returns VBox status code.
1130 * @param pVCpu The cross context virtual CPU structure.
1131 * @param pVmxTransient The VMX-transient structure.
1132 * @param uXcptMask The exception(s) to remove.
1133 */
1134static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1135{
1136 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1137 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1138 if (u32XcptBitmap & uXcptMask)
1139 {
1140#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1141 if (!pVmxTransient->fIsNestedGuest)
1142 { /* likely */ }
1143 else
1144 {
1145 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1146 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1147 }
1148#endif
1149#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1150 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1151 | RT_BIT(X86_XCPT_DE)
1152 | RT_BIT(X86_XCPT_NM)
1153 | RT_BIT(X86_XCPT_TS)
1154 | RT_BIT(X86_XCPT_UD)
1155 | RT_BIT(X86_XCPT_NP)
1156 | RT_BIT(X86_XCPT_SS)
1157 | RT_BIT(X86_XCPT_GP)
1158 | RT_BIT(X86_XCPT_PF)
1159 | RT_BIT(X86_XCPT_MF));
1160#elif defined(HMVMX_ALWAYS_TRAP_PF)
1161 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1162#endif
1163 if (uXcptMask)
1164 {
1165 /* Validate we are not removing any essential exception intercepts. */
1166 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1167 NOREF(pVCpu);
1168 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1169 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1170
1171 /* Remove it from the exception bitmap. */
1172 u32XcptBitmap &= ~uXcptMask;
1173
1174 /* Commit and update the cache if necessary. */
1175 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1176 {
1177 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1178 AssertRC(rc);
1179 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1180 }
1181 }
1182 }
1183 return VINF_SUCCESS;
1184}
1185
1186
1187/**
1188 * Remove an exceptions from the exception bitmap and commits it to the current
1189 * VMCS.
1190 *
1191 * @returns VBox status code.
1192 * @param pVCpu The cross context virtual CPU structure.
1193 * @param pVmxTransient The VMX-transient structure.
1194 * @param uXcpt The exception to remove.
1195 */
1196static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1197{
1198 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1199}
1200
1201
1202/**
1203 * Loads the VMCS specified by the VMCS info. object.
1204 *
1205 * @returns VBox status code.
1206 * @param pVmcsInfo The VMCS info. object.
1207 *
1208 * @remarks Can be called with interrupts disabled.
1209 */
1210static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1211{
1212 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1213 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1214
1215 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1216 if (RT_SUCCESS(rc))
1217 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1218 return rc;
1219}
1220
1221
1222/**
1223 * Clears the VMCS specified by the VMCS info. object.
1224 *
1225 * @returns VBox status code.
1226 * @param pVmcsInfo The VMCS info. object.
1227 *
1228 * @remarks Can be called with interrupts disabled.
1229 */
1230static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1231{
1232 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1233 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1234
1235 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1236 if (RT_SUCCESS(rc))
1237 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1238 return rc;
1239}
1240
1241
1242#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1243/**
1244 * Loads the shadow VMCS specified by the VMCS info. object.
1245 *
1246 * @returns VBox status code.
1247 * @param pVmcsInfo The VMCS info. object.
1248 *
1249 * @remarks Can be called with interrupts disabled.
1250 */
1251static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1252{
1253 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1254 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1255
1256 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1257 if (RT_SUCCESS(rc))
1258 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1259 return rc;
1260}
1261
1262
1263/**
1264 * Clears the shadow VMCS specified by the VMCS info. object.
1265 *
1266 * @returns VBox status code.
1267 * @param pVmcsInfo The VMCS info. object.
1268 *
1269 * @remarks Can be called with interrupts disabled.
1270 */
1271static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1272{
1273 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1274 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1275
1276 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1277 if (RT_SUCCESS(rc))
1278 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1279 return rc;
1280}
1281
1282
1283/**
1284 * Switches from and to the specified VMCSes.
1285 *
1286 * @returns VBox status code.
1287 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1288 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1289 *
1290 * @remarks Called with interrupts disabled.
1291 */
1292static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1293{
1294 /*
1295 * Clear the VMCS we are switching out if it has not already been cleared.
1296 * This will sync any CPU internal data back to the VMCS.
1297 */
1298 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1299 {
1300 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1301 if (RT_SUCCESS(rc))
1302 {
1303 /*
1304 * The shadow VMCS, if any, would not be active at this point since we
1305 * would have cleared it while importing the virtual hardware-virtualization
1306 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1307 * clear the shadow VMCS here, just assert for safety.
1308 */
1309 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1310 }
1311 else
1312 return rc;
1313 }
1314
1315 /*
1316 * Clear the VMCS we are switching to if it has not already been cleared.
1317 * This will initialize the VMCS launch state to "clear" required for loading it.
1318 *
1319 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1320 */
1321 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1322 {
1323 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1324 if (RT_SUCCESS(rc))
1325 { /* likely */ }
1326 else
1327 return rc;
1328 }
1329
1330 /*
1331 * Finally, load the VMCS we are switching to.
1332 */
1333 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1334}
1335
1336
1337/**
1338 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1339 * caller.
1340 *
1341 * @returns VBox status code.
1342 * @param pVCpu The cross context virtual CPU structure.
1343 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1344 * true) or guest VMCS (pass false).
1345 */
1346static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1347{
1348 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1349 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1350
1351 PVMXVMCSINFO pVmcsInfoFrom;
1352 PVMXVMCSINFO pVmcsInfoTo;
1353 if (fSwitchToNstGstVmcs)
1354 {
1355 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1356 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1357 }
1358 else
1359 {
1360 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1361 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1362 }
1363
1364 /*
1365 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1366 * preemption hook code path acquires the current VMCS.
1367 */
1368 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1369
1370 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1371 if (RT_SUCCESS(rc))
1372 {
1373 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1374
1375 /*
1376 * If we are switching to a VMCS that was executed on a different host CPU or was
1377 * never executed before, flag that we need to export the host state before executing
1378 * guest/nested-guest code using hardware-assisted VMX.
1379 *
1380 * This could probably be done in a preemptible context since the preemption hook
1381 * will flag the necessary change in host context. However, since preemption is
1382 * already disabled and to avoid making assumptions about host specific code in
1383 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1384 * disabled.
1385 */
1386 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1387 { /* likely */ }
1388 else
1389 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1390
1391 ASMSetFlags(fEFlags);
1392
1393 /*
1394 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1395 * flag that we need to update the host MSR values there. Even if we decide in the
1396 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1397 * if its content differs, we would have to update the host MSRs anyway.
1398 */
1399 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1400 }
1401 else
1402 ASMSetFlags(fEFlags);
1403 return rc;
1404}
1405#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1406
1407
1408/**
1409 * Updates the VM's last error record.
1410 *
1411 * If there was a VMX instruction error, reads the error data from the VMCS and
1412 * updates VCPU's last error record as well.
1413 *
1414 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1415 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1416 * VERR_VMX_INVALID_VMCS_FIELD.
1417 * @param rc The error code.
1418 */
1419static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1420{
1421 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1422 || rc == VERR_VMX_UNABLE_TO_START_VM)
1423 {
1424 AssertPtrReturnVoid(pVCpu);
1425 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1426 }
1427 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1428}
1429
1430
1431#ifdef VBOX_STRICT
1432/**
1433 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1434 * transient structure.
1435 *
1436 * @param pVmxTransient The VMX-transient structure.
1437 */
1438DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1439{
1440 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1441 AssertRC(rc);
1442}
1443
1444
1445/**
1446 * Reads the VM-entry exception error code field from the VMCS into
1447 * the VMX transient structure.
1448 *
1449 * @param pVmxTransient The VMX-transient structure.
1450 */
1451DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1452{
1453 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1454 AssertRC(rc);
1455}
1456
1457
1458/**
1459 * Reads the VM-entry exception error code field from the VMCS into
1460 * the VMX transient structure.
1461 *
1462 * @param pVmxTransient The VMX-transient structure.
1463 */
1464DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1465{
1466 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1467 AssertRC(rc);
1468}
1469#endif /* VBOX_STRICT */
1470
1471
1472/**
1473 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1474 * transient structure.
1475 *
1476 * @param pVmxTransient The VMX-transient structure.
1477 */
1478DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1479{
1480 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1481 {
1482 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1483 AssertRC(rc);
1484 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1485 }
1486}
1487
1488
1489/**
1490 * Reads the VM-exit interruption error code from the VMCS into the VMX
1491 * transient structure.
1492 *
1493 * @param pVmxTransient The VMX-transient structure.
1494 */
1495DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1496{
1497 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1498 {
1499 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1500 AssertRC(rc);
1501 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1502 }
1503}
1504
1505
1506/**
1507 * Reads the VM-exit instruction length field from the VMCS into the VMX
1508 * transient structure.
1509 *
1510 * @param pVmxTransient The VMX-transient structure.
1511 */
1512DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1513{
1514 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1515 {
1516 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1517 AssertRC(rc);
1518 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1519 }
1520}
1521
1522
1523/**
1524 * Reads the VM-exit instruction-information field from the VMCS into
1525 * the VMX transient structure.
1526 *
1527 * @param pVmxTransient The VMX-transient structure.
1528 */
1529DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1530{
1531 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1532 {
1533 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1534 AssertRC(rc);
1535 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1536 }
1537}
1538
1539
1540/**
1541 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1542 *
1543 * @param pVmxTransient The VMX-transient structure.
1544 */
1545DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1546{
1547 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1548 {
1549 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1550 AssertRC(rc);
1551 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1552 }
1553}
1554
1555
1556/**
1557 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1558 *
1559 * @param pVmxTransient The VMX-transient structure.
1560 */
1561DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1562{
1563 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1564 {
1565 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1566 AssertRC(rc);
1567 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1568 }
1569}
1570
1571
1572/**
1573 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1574 *
1575 * @param pVmxTransient The VMX-transient structure.
1576 */
1577DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1578{
1579 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1580 {
1581 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1582 AssertRC(rc);
1583 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1584 }
1585}
1586
1587#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1588/**
1589 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1590 * structure.
1591 *
1592 * @param pVmxTransient The VMX-transient structure.
1593 */
1594DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1595{
1596 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1597 {
1598 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1599 AssertRC(rc);
1600 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1601 }
1602}
1603#endif
1604
1605/**
1606 * Reads the IDT-vectoring information field from the VMCS into the VMX
1607 * transient structure.
1608 *
1609 * @param pVmxTransient The VMX-transient structure.
1610 *
1611 * @remarks No-long-jump zone!!!
1612 */
1613DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1614{
1615 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1616 {
1617 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1618 AssertRC(rc);
1619 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1620 }
1621}
1622
1623
1624/**
1625 * Reads the IDT-vectoring error code from the VMCS into the VMX
1626 * transient structure.
1627 *
1628 * @param pVmxTransient The VMX-transient structure.
1629 */
1630DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1631{
1632 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1633 {
1634 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1635 AssertRC(rc);
1636 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1637 }
1638}
1639
1640#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1641/**
1642 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1643 *
1644 * @param pVmxTransient The VMX-transient structure.
1645 */
1646static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1647{
1648 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1649 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1650 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1651 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1652 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1653 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1654 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1655 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1656 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1657 AssertRC(rc);
1658 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1659 | HMVMX_READ_EXIT_INSTR_LEN
1660 | HMVMX_READ_EXIT_INSTR_INFO
1661 | HMVMX_READ_IDT_VECTORING_INFO
1662 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1663 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1664 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1665 | HMVMX_READ_GUEST_LINEAR_ADDR
1666 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1667}
1668#endif
1669
1670/**
1671 * Enters VMX root mode operation on the current CPU.
1672 *
1673 * @returns VBox status code.
1674 * @param pHostCpu The HM physical-CPU structure.
1675 * @param pVM The cross context VM structure. Can be
1676 * NULL, after a resume.
1677 * @param HCPhysCpuPage Physical address of the VMXON region.
1678 * @param pvCpuPage Pointer to the VMXON region.
1679 */
1680static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1681{
1682 Assert(pHostCpu);
1683 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1684 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1685 Assert(pvCpuPage);
1686 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1687
1688 if (pVM)
1689 {
1690 /* Write the VMCS revision identifier to the VMXON region. */
1691 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1692 }
1693
1694 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1695 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1696
1697 /* Enable the VMX bit in CR4 if necessary. */
1698 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1699
1700 /* Record whether VMXE was already prior to us enabling it above. */
1701 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1702
1703 /* Enter VMX root mode. */
1704 int rc = VMXEnable(HCPhysCpuPage);
1705 if (RT_FAILURE(rc))
1706 {
1707 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1708 if (!pHostCpu->fVmxeAlreadyEnabled)
1709 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1710
1711 if (pVM)
1712 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1713 }
1714
1715 /* Restore interrupts. */
1716 ASMSetFlags(fEFlags);
1717 return rc;
1718}
1719
1720
1721/**
1722 * Exits VMX root mode operation on the current CPU.
1723 *
1724 * @returns VBox status code.
1725 * @param pHostCpu The HM physical-CPU structure.
1726 */
1727static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1728{
1729 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1730
1731 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1732 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1733
1734 /* If we're for some reason not in VMX root mode, then don't leave it. */
1735 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1736
1737 int rc;
1738 if (uHostCr4 & X86_CR4_VMXE)
1739 {
1740 /* Exit VMX root mode and clear the VMX bit in CR4. */
1741 VMXDisable();
1742
1743 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1744 if (!pHostCpu->fVmxeAlreadyEnabled)
1745 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1746
1747 rc = VINF_SUCCESS;
1748 }
1749 else
1750 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1751
1752 /* Restore interrupts. */
1753 ASMSetFlags(fEFlags);
1754 return rc;
1755}
1756
1757
1758/**
1759 * Allocates pages specified as specified by an array of VMX page allocation info
1760 * objects.
1761 *
1762 * The pages contents are zero'd after allocation.
1763 *
1764 * @returns VBox status code.
1765 * @param hMemObj The ring-0 memory object associated with the allocation.
1766 * @param paAllocInfo The pointer to the first element of the VMX
1767 * page-allocation info object array.
1768 * @param cEntries The number of elements in the @a paAllocInfo array.
1769 */
1770static int hmR0VmxPagesAllocZ(RTR0MEMOBJ hMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1771{
1772 /* Figure out how many pages to allocate. */
1773 uint32_t cPages = 0;
1774 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1775 cPages += !!paAllocInfo[iPage].fValid;
1776
1777 /* Allocate the pages. */
1778 if (cPages)
1779 {
1780 size_t const cbPages = cPages << X86_PAGE_4K_SHIFT;
1781 int rc = RTR0MemObjAllocPage(&hMemObj, cbPages, false /* fExecutable */);
1782 if (RT_FAILURE(rc))
1783 return rc;
1784
1785 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1786 void *pvFirstPage = RTR0MemObjAddress(hMemObj);
1787 ASMMemZero32(pvFirstPage, cbPages);
1788
1789 uint32_t iPage = 0;
1790 for (uint32_t i = 0; i < cEntries; i++)
1791 if (paAllocInfo[i].fValid)
1792 {
1793 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(hMemObj, iPage);
1794 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1795 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1796 AssertPtr(pvPage);
1797
1798 Assert(paAllocInfo[iPage].pHCPhys);
1799 Assert(paAllocInfo[iPage].ppVirt);
1800 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1801 *paAllocInfo[iPage].ppVirt = pvPage;
1802
1803 /* Move to next page. */
1804 ++iPage;
1805 }
1806
1807 /* Make sure all valid (requested) pages have been assigned. */
1808 Assert(iPage == cPages);
1809 }
1810 return VINF_SUCCESS;
1811}
1812
1813
1814/**
1815 * Frees pages allocated using hmR0VmxPagesAllocZ.
1816 *
1817 * @param hMemObj The ring-0 memory object associated with the allocation.
1818 */
1819DECL_FORCE_INLINE(void) hmR0VmxPagesFree(RTR0MEMOBJ hMemObj)
1820{
1821 /* We can cleanup wholesale since it's all one allocation. */
1822 RTR0MemObjFree(hMemObj, true /* fFreeMappings */);
1823}
1824
1825
1826/**
1827 * Initializes a VMCS info. object.
1828 *
1829 * @param pVmcsInfo The VMCS info. object.
1830 */
1831static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo)
1832{
1833 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1834
1835 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1836 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1837 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1838 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1839 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1840 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1841 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1842 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1843 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1844 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1845 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1846 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1847}
1848
1849
1850/**
1851 * Frees the VT-x structures for a VMCS info. object.
1852 *
1853 * @param pVmcsInfo The VMCS info. object.
1854 */
1855static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo)
1856{
1857 if (pVmcsInfo->hMemObj != NIL_RTR0MEMOBJ)
1858 {
1859 hmR0VmxPagesFree(pVmcsInfo->hMemObj);
1860 hmR0VmxVmcsInfoInit(pVmcsInfo);
1861 }
1862}
1863
1864
1865/**
1866 * Allocates the VT-x structures for a VMCS info. object.
1867 *
1868 * @returns VBox status code.
1869 * @param pVCpu The cross context virtual CPU structure.
1870 * @param pVmcsInfo The VMCS info. object.
1871 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1872 *
1873 * @remarks The caller is expected to take care of any and all allocation failures.
1874 * This function will not perform any cleanup for failures half-way
1875 * through.
1876 */
1877static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1878{
1879 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1880
1881 bool const fMsrBitmaps = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1882 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hm.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1883 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1884 VMXPAGEALLOCINFO aAllocInfo[] = {
1885 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1886 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1887 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1888 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1889 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1890 };
1891
1892 int rc = hmR0VmxPagesAllocZ(pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1893 if (RT_FAILURE(rc))
1894 return rc;
1895
1896 /*
1897 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1898 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1899 */
1900 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1901 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1902 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1903 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1904
1905 /*
1906 * Get the virtual-APIC page rather than allocating them again.
1907 */
1908 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1909 {
1910 if (!fIsNstGstVmcs)
1911 {
1912 if (PDMHasApic(pVM))
1913 {
1914 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1915 if (RT_FAILURE(rc))
1916 return rc;
1917 Assert(pVmcsInfo->pbVirtApic);
1918 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1919 }
1920 }
1921 else
1922 {
1923 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1924 Assert(pVmcsInfo->pbVirtApic);
1925 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1926 }
1927 }
1928
1929 return VINF_SUCCESS;
1930}
1931
1932
1933/**
1934 * Free all VT-x structures for the VM.
1935 *
1936 * @returns IPRT status code.
1937 * @param pVM The cross context VM structure.
1938 */
1939static void hmR0VmxStructsFree(PVMCC pVM)
1940{
1941 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1942#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1943 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1944 {
1945 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1946 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1947 }
1948#endif
1949
1950 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1951 {
1952 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1953 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfo);
1954#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1955 if (pVM->cpum.ro.GuestFeatures.fVmx)
1956 hmR0VmxVmcsInfoFree(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1957#endif
1958 }
1959}
1960
1961
1962/**
1963 * Allocate all VT-x structures for the VM.
1964 *
1965 * @returns IPRT status code.
1966 * @param pVM The cross context VM structure.
1967 *
1968 * @remarks This functions will cleanup on memory allocation failures.
1969 */
1970static int hmR0VmxStructsAlloc(PVMCC pVM)
1971{
1972 /*
1973 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1974 * The VMCS size cannot be more than 4096 bytes.
1975 *
1976 * See Intel spec. Appendix A.1 "Basic VMX Information".
1977 */
1978 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1979 if (cbVmcs <= X86_PAGE_4K_SIZE)
1980 { /* likely */ }
1981 else
1982 {
1983 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1984 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1985 }
1986
1987 /*
1988 * Allocate per-VM VT-x structures.
1989 */
1990 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
1991 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
1992 VMXPAGEALLOCINFO aAllocInfo[] = {
1993 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
1994 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
1995 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
1996#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1997 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
1998#endif
1999 };
2000
2001 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2002 if (RT_FAILURE(rc))
2003 goto cleanup;
2004
2005#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2006 /* Allocate the shadow VMCS-fields array. */
2007 if (fUseVmcsShadowing)
2008 {
2009 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
2010 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
2011 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2012 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2013 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
2014 && pVM->hm.s.vmx.paShadowVmcsRoFields))
2015 { /* likely */ }
2016 else
2017 {
2018 rc = VERR_NO_MEMORY;
2019 goto cleanup;
2020 }
2021 }
2022#endif
2023
2024 /*
2025 * Allocate per-VCPU VT-x structures.
2026 */
2027 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2028 {
2029 /* Allocate the guest VMCS structures. */
2030 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2031 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2032 if (RT_FAILURE(rc))
2033 goto cleanup;
2034
2035#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2036 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2037 if (pVM->cpum.ro.GuestFeatures.fVmx)
2038 {
2039 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2040 if (RT_FAILURE(rc))
2041 goto cleanup;
2042 }
2043#endif
2044 }
2045
2046 return VINF_SUCCESS;
2047
2048cleanup:
2049 hmR0VmxStructsFree(pVM);
2050 Assert(rc != VINF_SUCCESS);
2051 return rc;
2052}
2053
2054
2055/**
2056 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2057 *
2058 * @param pVM The cross context VM structure.
2059 */
2060static void hmR0VmxStructsInit(PVMCC pVM)
2061{
2062 /* Paranoia. */
2063 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2064#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2065 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2066#endif
2067
2068 /*
2069 * Initialize members up-front so we can cleanup en masse on allocation failures.
2070 */
2071#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2072 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2073#endif
2074 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2075 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2076 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2077 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2078 {
2079 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2080 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfo);
2081 hmR0VmxVmcsInfoInit(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
2082 }
2083}
2084
2085#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2086/**
2087 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2088 *
2089 * @returns @c true if the MSR is intercepted, @c false otherwise.
2090 * @param pvMsrBitmap The MSR bitmap.
2091 * @param offMsr The MSR byte offset.
2092 * @param iBit The bit offset from the byte offset.
2093 */
2094DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2095{
2096 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2097 Assert(pbMsrBitmap);
2098 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2099 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2100}
2101#endif
2102
2103/**
2104 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2105 *
2106 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2107 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2108 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2109 * the read/write access of this MSR.
2110 *
2111 * @param pVCpu The cross context virtual CPU structure.
2112 * @param pVmcsInfo The VMCS info. object.
2113 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2114 * @param idMsr The MSR value.
2115 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2116 * include both a read -and- a write permission!
2117 *
2118 * @sa CPUMGetVmxMsrPermission.
2119 * @remarks Can be called with interrupts disabled.
2120 */
2121static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2122{
2123 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2124 Assert(pbMsrBitmap);
2125 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2126
2127 /*
2128 * MSR-bitmap Layout:
2129 * Byte index MSR range Interpreted as
2130 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2131 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2132 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2133 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2134 *
2135 * A bit corresponding to an MSR within the above range causes a VM-exit
2136 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2137 * the MSR range, it always cause a VM-exit.
2138 *
2139 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2140 */
2141 uint16_t const offBitmapRead = 0;
2142 uint16_t const offBitmapWrite = 0x800;
2143 uint16_t offMsr;
2144 int32_t iBit;
2145 if (idMsr <= UINT32_C(0x00001fff))
2146 {
2147 offMsr = 0;
2148 iBit = idMsr;
2149 }
2150 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2151 {
2152 offMsr = 0x400;
2153 iBit = idMsr - UINT32_C(0xc0000000);
2154 }
2155 else
2156 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2157
2158 /*
2159 * Set the MSR read permission.
2160 */
2161 uint16_t const offMsrRead = offBitmapRead + offMsr;
2162 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2163 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2164 {
2165#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2166 bool const fClear = !fIsNstGstVmcs ? true
2167 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2168#else
2169 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2170 bool const fClear = true;
2171#endif
2172 if (fClear)
2173 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2174 }
2175 else
2176 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2177
2178 /*
2179 * Set the MSR write permission.
2180 */
2181 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2182 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2183 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2184 {
2185#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2186 bool const fClear = !fIsNstGstVmcs ? true
2187 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2188#else
2189 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2190 bool const fClear = true;
2191#endif
2192 if (fClear)
2193 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2194 }
2195 else
2196 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2197}
2198
2199
2200/**
2201 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2202 * area.
2203 *
2204 * @returns VBox status code.
2205 * @param pVCpu The cross context virtual CPU structure.
2206 * @param pVmcsInfo The VMCS info. object.
2207 * @param cMsrs The number of MSRs.
2208 */
2209static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2210{
2211 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2212 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2213 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2214 {
2215 /* Commit the MSR counts to the VMCS and update the cache. */
2216 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2217 {
2218 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2219 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2220 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2221 pVmcsInfo->cEntryMsrLoad = cMsrs;
2222 pVmcsInfo->cExitMsrStore = cMsrs;
2223 pVmcsInfo->cExitMsrLoad = cMsrs;
2224 }
2225 return VINF_SUCCESS;
2226 }
2227
2228 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2229 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2230 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2231}
2232
2233
2234/**
2235 * Adds a new (or updates the value of an existing) guest/host MSR
2236 * pair to be swapped during the world-switch as part of the
2237 * auto-load/store MSR area in the VMCS.
2238 *
2239 * @returns VBox status code.
2240 * @param pVCpu The cross context virtual CPU structure.
2241 * @param pVmxTransient The VMX-transient structure.
2242 * @param idMsr The MSR.
2243 * @param uGuestMsrValue Value of the guest MSR.
2244 * @param fSetReadWrite Whether to set the guest read/write access of this
2245 * MSR (thus not causing a VM-exit).
2246 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2247 * necessary.
2248 */
2249static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2250 bool fSetReadWrite, bool fUpdateHostMsr)
2251{
2252 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2253 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2254 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2255 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2256 uint32_t i;
2257
2258 /* Paranoia. */
2259 Assert(pGuestMsrLoad);
2260
2261 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2262
2263 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2264 for (i = 0; i < cMsrs; i++)
2265 {
2266 if (pGuestMsrLoad[i].u32Msr == idMsr)
2267 break;
2268 }
2269
2270 bool fAdded = false;
2271 if (i == cMsrs)
2272 {
2273 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2274 ++cMsrs;
2275 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2276 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2277
2278 /* Set the guest to read/write this MSR without causing VM-exits. */
2279 if ( fSetReadWrite
2280 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2281 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2282
2283 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2284 fAdded = true;
2285 }
2286
2287 /* Update the MSR value for the newly added or already existing MSR. */
2288 pGuestMsrLoad[i].u32Msr = idMsr;
2289 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2290
2291 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2292 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2293 {
2294 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2295 pGuestMsrStore[i].u32Msr = idMsr;
2296 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2297 }
2298
2299 /* Update the corresponding slot in the host MSR area. */
2300 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2301 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2302 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2303 pHostMsr[i].u32Msr = idMsr;
2304
2305 /*
2306 * Only if the caller requests to update the host MSR value AND we've newly added the
2307 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2308 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2309 *
2310 * We do this for performance reasons since reading MSRs may be quite expensive.
2311 */
2312 if (fAdded)
2313 {
2314 if (fUpdateHostMsr)
2315 {
2316 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2317 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2318 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2319 }
2320 else
2321 {
2322 /* Someone else can do the work. */
2323 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2324 }
2325 }
2326 return VINF_SUCCESS;
2327}
2328
2329
2330/**
2331 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2332 * auto-load/store MSR area in the VMCS.
2333 *
2334 * @returns VBox status code.
2335 * @param pVCpu The cross context virtual CPU structure.
2336 * @param pVmxTransient The VMX-transient structure.
2337 * @param idMsr The MSR.
2338 */
2339static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2340{
2341 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2342 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2343 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2344 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2345
2346 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2347
2348 for (uint32_t i = 0; i < cMsrs; i++)
2349 {
2350 /* Find the MSR. */
2351 if (pGuestMsrLoad[i].u32Msr == idMsr)
2352 {
2353 /*
2354 * If it's the last MSR, we only need to reduce the MSR count.
2355 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2356 */
2357 if (i < cMsrs - 1)
2358 {
2359 /* Remove it from the VM-entry MSR-load area. */
2360 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2361 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2362
2363 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2364 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2365 {
2366 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2367 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2368 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2369 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2370 }
2371
2372 /* Remove it from the VM-exit MSR-load area. */
2373 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2374 Assert(pHostMsr[i].u32Msr == idMsr);
2375 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2376 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2377 }
2378
2379 /* Reduce the count to reflect the removed MSR and bail. */
2380 --cMsrs;
2381 break;
2382 }
2383 }
2384
2385 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2386 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2387 {
2388 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2389 AssertRCReturn(rc, rc);
2390
2391 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2392 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2393 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2394
2395 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2396 return VINF_SUCCESS;
2397 }
2398
2399 return VERR_NOT_FOUND;
2400}
2401
2402
2403/**
2404 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2405 *
2406 * @returns @c true if found, @c false otherwise.
2407 * @param pVmcsInfo The VMCS info. object.
2408 * @param idMsr The MSR to find.
2409 */
2410static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2411{
2412 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2413 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2414 Assert(pMsrs);
2415 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2416 for (uint32_t i = 0; i < cMsrs; i++)
2417 {
2418 if (pMsrs[i].u32Msr == idMsr)
2419 return true;
2420 }
2421 return false;
2422}
2423
2424
2425/**
2426 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2427 *
2428 * @param pVCpu The cross context virtual CPU structure.
2429 * @param pVmcsInfo The VMCS info. object.
2430 *
2431 * @remarks No-long-jump zone!!!
2432 */
2433static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2434{
2435 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2436
2437 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2438 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2439 Assert(pHostMsrLoad);
2440 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2441 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2442 for (uint32_t i = 0; i < cMsrs; i++)
2443 {
2444 /*
2445 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2446 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2447 */
2448 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2449 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2450 else
2451 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2452 }
2453}
2454
2455
2456/**
2457 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2458 * perform lazy restoration of the host MSRs while leaving VT-x.
2459 *
2460 * @param pVCpu The cross context virtual CPU structure.
2461 *
2462 * @remarks No-long-jump zone!!!
2463 */
2464static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2465{
2466 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2467
2468 /*
2469 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2470 */
2471 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2472 {
2473 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2474 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2475 {
2476 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2477 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2478 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2479 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2480 }
2481 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2482 }
2483}
2484
2485
2486/**
2487 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2488 * lazily while leaving VT-x.
2489 *
2490 * @returns true if it does, false otherwise.
2491 * @param pVCpu The cross context virtual CPU structure.
2492 * @param idMsr The MSR to check.
2493 */
2494static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2495{
2496 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2497 {
2498 switch (idMsr)
2499 {
2500 case MSR_K8_LSTAR:
2501 case MSR_K6_STAR:
2502 case MSR_K8_SF_MASK:
2503 case MSR_K8_KERNEL_GS_BASE:
2504 return true;
2505 }
2506 }
2507 return false;
2508}
2509
2510
2511/**
2512 * Loads a set of guests MSRs to allow read/passthru to the guest.
2513 *
2514 * The name of this function is slightly confusing. This function does NOT
2515 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2516 * common prefix for functions dealing with "lazy restoration" of the shared
2517 * MSRs.
2518 *
2519 * @param pVCpu The cross context virtual CPU structure.
2520 *
2521 * @remarks No-long-jump zone!!!
2522 */
2523static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2524{
2525 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2526 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2527
2528 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2529 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2530 {
2531 /*
2532 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2533 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2534 * we can skip a few MSR writes.
2535 *
2536 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2537 * guest MSR values in the guest-CPU context might be different to what's currently
2538 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2539 * CPU, see @bugref{8728}.
2540 */
2541 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2542 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2543 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2544 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2545 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2546 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2547 {
2548#ifdef VBOX_STRICT
2549 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2550 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2551 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2552 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2553#endif
2554 }
2555 else
2556 {
2557 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2558 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2559 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2560 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2561 }
2562 }
2563 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2564}
2565
2566
2567/**
2568 * Performs lazy restoration of the set of host MSRs if they were previously
2569 * loaded with guest MSR values.
2570 *
2571 * @param pVCpu The cross context virtual CPU structure.
2572 *
2573 * @remarks No-long-jump zone!!!
2574 * @remarks The guest MSRs should have been saved back into the guest-CPU
2575 * context by hmR0VmxImportGuestState()!!!
2576 */
2577static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2578{
2579 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2580 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2581
2582 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2583 {
2584 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2585 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2586 {
2587 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2588 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2589 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2590 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2591 }
2592 }
2593 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2594}
2595
2596
2597/**
2598 * Verifies that our cached values of the VMCS fields are all consistent with
2599 * what's actually present in the VMCS.
2600 *
2601 * @returns VBox status code.
2602 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2603 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2604 * VMCS content. HMCPU error-field is
2605 * updated, see VMX_VCI_XXX.
2606 * @param pVCpu The cross context virtual CPU structure.
2607 * @param pVmcsInfo The VMCS info. object.
2608 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2609 */
2610static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2611{
2612 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2613
2614 uint32_t u32Val;
2615 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2616 AssertRC(rc);
2617 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2618 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2619 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2620 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2621
2622 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2623 AssertRC(rc);
2624 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2625 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2626 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2627 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2628
2629 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2630 AssertRC(rc);
2631 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2632 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2633 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2634 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2635
2636 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2637 AssertRC(rc);
2638 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2639 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2640 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2641 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2642
2643 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2644 {
2645 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2646 AssertRC(rc);
2647 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2648 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2649 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2650 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2651 }
2652
2653 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2654 AssertRC(rc);
2655 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2656 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2657 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2658 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2659
2660 uint64_t u64Val;
2661 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2662 AssertRC(rc);
2663 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2664 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2665 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2666 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2667
2668 NOREF(pcszVmcs);
2669 return VINF_SUCCESS;
2670}
2671
2672
2673#ifdef VBOX_STRICT
2674/**
2675 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2676 *
2677 * @param pVCpu The cross context virtual CPU structure.
2678 * @param pVmcsInfo The VMCS info. object.
2679 */
2680static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2681{
2682 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2683
2684 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2685 {
2686 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2687 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2688 uint64_t uVmcsEferMsrVmcs;
2689 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2690 AssertRC(rc);
2691
2692 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2693 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2694 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2695 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2696 }
2697}
2698
2699
2700/**
2701 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2702 * VMCS are correct.
2703 *
2704 * @param pVCpu The cross context virtual CPU structure.
2705 * @param pVmcsInfo The VMCS info. object.
2706 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2707 */
2708static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2709{
2710 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2711
2712 /* Read the various MSR-area counts from the VMCS. */
2713 uint32_t cEntryLoadMsrs;
2714 uint32_t cExitStoreMsrs;
2715 uint32_t cExitLoadMsrs;
2716 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2717 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2718 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2719
2720 /* Verify all the MSR counts are the same. */
2721 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2722 Assert(cExitStoreMsrs == cExitLoadMsrs);
2723 uint32_t const cMsrs = cExitLoadMsrs;
2724
2725 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2726 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2727
2728 /* Verify the MSR counts are within the allocated page size. */
2729 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2730
2731 /* Verify the relevant contents of the MSR areas match. */
2732 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2733 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2734 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2735 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2736 for (uint32_t i = 0; i < cMsrs; i++)
2737 {
2738 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2739 if (fSeparateExitMsrStorePage)
2740 {
2741 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2742 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2743 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2744 }
2745
2746 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2747 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2748 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2749
2750 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2751 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2752 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2753 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2754
2755 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2756 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2757 if (fIsEferMsr)
2758 {
2759 AssertMsgReturnVoid(u64HostMsr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2760 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2761 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64HostMsr, cMsrs));
2762 }
2763
2764 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2765 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2766 {
2767 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2768 if (fIsEferMsr)
2769 {
2770 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2771 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2772 }
2773 else
2774 {
2775 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2776 PCVM pVM = pVCpu->CTX_SUFF(pVM);
2777 if ( pVM->hm.s.vmx.fLbr
2778 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2779 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2780 || pGuestMsrLoad->u32Msr == pVM->hm.s.vmx.idLbrTosMsr))
2781 {
2782 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2783 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2784 pGuestMsrLoad->u32Msr, cMsrs));
2785 }
2786 else if (!fIsNstGstVmcs)
2787 {
2788 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2789 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2790 }
2791 else
2792 {
2793 /*
2794 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2795 * execute a nested-guest with MSR passthrough.
2796 *
2797 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2798 * allow passthrough too.
2799 */
2800 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2801 Assert(pvMsrBitmapNstGst);
2802 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2803 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2804 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2805 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2806 }
2807 }
2808 }
2809
2810 /* Move to the next MSR. */
2811 pHostMsrLoad++;
2812 pGuestMsrLoad++;
2813 pGuestMsrStore++;
2814 }
2815}
2816#endif /* VBOX_STRICT */
2817
2818
2819/**
2820 * Flushes the TLB using EPT.
2821 *
2822 * @returns VBox status code.
2823 * @param pVCpu The cross context virtual CPU structure of the calling
2824 * EMT. Can be NULL depending on @a enmTlbFlush.
2825 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2826 * enmTlbFlush.
2827 * @param enmTlbFlush Type of flush.
2828 *
2829 * @remarks Caller is responsible for making sure this function is called only
2830 * when NestedPaging is supported and providing @a enmTlbFlush that is
2831 * supported by the CPU.
2832 * @remarks Can be called with interrupts disabled.
2833 */
2834static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2835{
2836 uint64_t au64Descriptor[2];
2837 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2838 au64Descriptor[0] = 0;
2839 else
2840 {
2841 Assert(pVCpu);
2842 Assert(pVmcsInfo);
2843 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2844 }
2845 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2846
2847 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2848 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2849
2850 if ( RT_SUCCESS(rc)
2851 && pVCpu)
2852 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2853}
2854
2855
2856/**
2857 * Flushes the TLB using VPID.
2858 *
2859 * @returns VBox status code.
2860 * @param pVCpu The cross context virtual CPU structure of the calling
2861 * EMT. Can be NULL depending on @a enmTlbFlush.
2862 * @param enmTlbFlush Type of flush.
2863 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2864 * on @a enmTlbFlush).
2865 *
2866 * @remarks Can be called with interrupts disabled.
2867 */
2868static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2869{
2870 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2871
2872 uint64_t au64Descriptor[2];
2873 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2874 {
2875 au64Descriptor[0] = 0;
2876 au64Descriptor[1] = 0;
2877 }
2878 else
2879 {
2880 AssertPtr(pVCpu);
2881 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2882 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2883 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2884 au64Descriptor[1] = GCPtr;
2885 }
2886
2887 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2888 AssertMsg(rc == VINF_SUCCESS,
2889 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2890
2891 if ( RT_SUCCESS(rc)
2892 && pVCpu)
2893 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2894 NOREF(rc);
2895}
2896
2897
2898/**
2899 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2900 * otherwise there is nothing really to invalidate.
2901 *
2902 * @returns VBox status code.
2903 * @param pVCpu The cross context virtual CPU structure.
2904 * @param GCVirt Guest virtual address of the page to invalidate.
2905 */
2906VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2907{
2908 AssertPtr(pVCpu);
2909 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2910
2911 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2912 {
2913 /*
2914 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2915 * the EPT case. See @bugref{6043} and @bugref{6177}.
2916 *
2917 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2918 * as this function maybe called in a loop with individual addresses.
2919 */
2920 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2921 if (pVM->hm.s.vmx.fVpid)
2922 {
2923 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2924 if (fVpidFlush)
2925 {
2926 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2927 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2928 }
2929 else
2930 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2931 }
2932 else if (pVM->hm.s.fNestedPaging)
2933 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2934 }
2935
2936 return VINF_SUCCESS;
2937}
2938
2939
2940/**
2941 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2942 * case where neither EPT nor VPID is supported by the CPU.
2943 *
2944 * @param pHostCpu The HM physical-CPU structure.
2945 * @param pVCpu The cross context virtual CPU structure.
2946 *
2947 * @remarks Called with interrupts disabled.
2948 */
2949static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2950{
2951 AssertPtr(pVCpu);
2952 AssertPtr(pHostCpu);
2953
2954 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2955
2956 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2957 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2958 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2959 pVCpu->hm.s.fForceTLBFlush = false;
2960 return;
2961}
2962
2963
2964/**
2965 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2966 *
2967 * @param pHostCpu The HM physical-CPU structure.
2968 * @param pVCpu The cross context virtual CPU structure.
2969 * @param pVmcsInfo The VMCS info. object.
2970 *
2971 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2972 * nomenclature. The reason is, to avoid confusion in compare statements
2973 * since the host-CPU copies are named "ASID".
2974 *
2975 * @remarks Called with interrupts disabled.
2976 */
2977static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2978{
2979#ifdef VBOX_WITH_STATISTICS
2980 bool fTlbFlushed = false;
2981# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2982# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2983 if (!fTlbFlushed) \
2984 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2985 } while (0)
2986#else
2987# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2988# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2989#endif
2990
2991 AssertPtr(pVCpu);
2992 AssertPtr(pHostCpu);
2993 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2994
2995 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2996 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2997 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2998 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2999
3000 /*
3001 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3002 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3003 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3004 * cannot reuse the current ASID anymore.
3005 */
3006 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3007 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3008 {
3009 ++pHostCpu->uCurrentAsid;
3010 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3011 {
3012 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3013 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3014 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3015 }
3016
3017 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3018 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3019 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3020
3021 /*
3022 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3023 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3024 */
3025 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3026 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3027 HMVMX_SET_TAGGED_TLB_FLUSHED();
3028 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3029 }
3030 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3031 {
3032 /*
3033 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3034 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3035 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3036 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3037 * mappings, see @bugref{6568}.
3038 *
3039 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3040 */
3041 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3042 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3043 HMVMX_SET_TAGGED_TLB_FLUSHED();
3044 }
3045 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3046 {
3047 /*
3048 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3049 * address which requires flushing the TLB of EPT cached structures.
3050 *
3051 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3052 */
3053 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3054 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3055 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3056 HMVMX_SET_TAGGED_TLB_FLUSHED();
3057 }
3058
3059
3060 pVCpu->hm.s.fForceTLBFlush = false;
3061 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3062
3063 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
3064 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3065 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3066 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3067 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3068 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3069 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3070 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3071 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3072
3073 /* Update VMCS with the VPID. */
3074 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3075 AssertRC(rc);
3076
3077#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3078}
3079
3080
3081/**
3082 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3083 *
3084 * @param pHostCpu The HM physical-CPU structure.
3085 * @param pVCpu The cross context virtual CPU structure.
3086 * @param pVmcsInfo The VMCS info. object.
3087 *
3088 * @remarks Called with interrupts disabled.
3089 */
3090static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3091{
3092 AssertPtr(pVCpu);
3093 AssertPtr(pHostCpu);
3094 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3095 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3096 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3097
3098 /*
3099 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3100 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3101 */
3102 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3103 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3104 {
3105 pVCpu->hm.s.fForceTLBFlush = true;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3107 }
3108
3109 /* Check for explicit TLB flushes. */
3110 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3111 {
3112 pVCpu->hm.s.fForceTLBFlush = true;
3113 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3114 }
3115
3116 /* Check for TLB flushes while switching to/from a nested-guest. */
3117 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3118 {
3119 pVCpu->hm.s.fForceTLBFlush = true;
3120 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3121 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3122 }
3123
3124 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3125 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3126
3127 if (pVCpu->hm.s.fForceTLBFlush)
3128 {
3129 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3130 pVCpu->hm.s.fForceTLBFlush = false;
3131 }
3132}
3133
3134
3135/**
3136 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3137 *
3138 * @param pHostCpu The HM physical-CPU structure.
3139 * @param pVCpu The cross context virtual CPU structure.
3140 *
3141 * @remarks Called with interrupts disabled.
3142 */
3143static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3144{
3145 AssertPtr(pVCpu);
3146 AssertPtr(pHostCpu);
3147 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3148 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3149 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3150
3151 /*
3152 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3153 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3154 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3155 * cannot reuse the current ASID anymore.
3156 */
3157 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3158 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3159 {
3160 pVCpu->hm.s.fForceTLBFlush = true;
3161 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3162 }
3163
3164 /* Check for explicit TLB flushes. */
3165 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3166 {
3167 /*
3168 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3169 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3170 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3171 * include fExplicitFlush's too) - an obscure corner case.
3172 */
3173 pVCpu->hm.s.fForceTLBFlush = true;
3174 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3175 }
3176
3177 /* Check for TLB flushes while switching to/from a nested-guest. */
3178 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3179 {
3180 pVCpu->hm.s.fForceTLBFlush = true;
3181 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3182 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3183 }
3184
3185 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3186 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3187 if (pVCpu->hm.s.fForceTLBFlush)
3188 {
3189 ++pHostCpu->uCurrentAsid;
3190 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3191 {
3192 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3193 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3194 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3195 }
3196
3197 pVCpu->hm.s.fForceTLBFlush = false;
3198 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3199 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3200 if (pHostCpu->fFlushAsidBeforeUse)
3201 {
3202 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3203 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3204 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3205 {
3206 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3207 pHostCpu->fFlushAsidBeforeUse = false;
3208 }
3209 else
3210 {
3211 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3212 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3213 }
3214 }
3215 }
3216
3217 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3218 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3219 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3220 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3221 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3222 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3223 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3224
3225 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3226 AssertRC(rc);
3227}
3228
3229
3230/**
3231 * Flushes the guest TLB entry based on CPU capabilities.
3232 *
3233 * @param pHostCpu The HM physical-CPU structure.
3234 * @param pVCpu The cross context virtual CPU structure.
3235 * @param pVmcsInfo The VMCS info. object.
3236 *
3237 * @remarks Called with interrupts disabled.
3238 */
3239static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3240{
3241#ifdef HMVMX_ALWAYS_FLUSH_TLB
3242 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3243#endif
3244 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3245 switch (pVM->hm.s.vmx.enmTlbFlushType)
3246 {
3247 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3248 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3249 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3250 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3251 default:
3252 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3253 break;
3254 }
3255 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3256}
3257
3258
3259/**
3260 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3261 * TLB entries from the host TLB before VM-entry.
3262 *
3263 * @returns VBox status code.
3264 * @param pVM The cross context VM structure.
3265 */
3266static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3267{
3268 /*
3269 * Determine optimal flush type for nested paging.
3270 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3271 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3272 */
3273 if (pVM->hm.s.fNestedPaging)
3274 {
3275 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3276 {
3277 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3278 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3279 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3280 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3281 else
3282 {
3283 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3284 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3285 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3286 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3287 }
3288
3289 /* Make sure the write-back cacheable memory type for EPT is supported. */
3290 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3291 {
3292 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3293 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3294 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3295 }
3296
3297 /* EPT requires a page-walk length of 4. */
3298 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3299 {
3300 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3301 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3302 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3303 }
3304 }
3305 else
3306 {
3307 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3308 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3309 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3310 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3311 }
3312 }
3313
3314 /*
3315 * Determine optimal flush type for VPID.
3316 */
3317 if (pVM->hm.s.vmx.fVpid)
3318 {
3319 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3320 {
3321 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3322 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3323 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3324 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3325 else
3326 {
3327 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3328 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3329 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3330 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3331 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3332 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3333 pVM->hm.s.vmx.fVpid = false;
3334 }
3335 }
3336 else
3337 {
3338 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3339 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3340 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3341 pVM->hm.s.vmx.fVpid = false;
3342 }
3343 }
3344
3345 /*
3346 * Setup the handler for flushing tagged-TLBs.
3347 */
3348 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3349 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3350 else if (pVM->hm.s.fNestedPaging)
3351 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3352 else if (pVM->hm.s.vmx.fVpid)
3353 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3354 else
3355 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3356 return VINF_SUCCESS;
3357}
3358
3359
3360/**
3361 * Sets up the LBR MSR ranges based on the host CPU.
3362 *
3363 * @returns VBox status code.
3364 * @param pVM The cross context VM structure.
3365 */
3366static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3367{
3368 Assert(pVM->hm.s.vmx.fLbr);
3369 uint32_t idLbrFromIpMsrFirst;
3370 uint32_t idLbrFromIpMsrLast;
3371 uint32_t idLbrToIpMsrFirst;
3372 uint32_t idLbrToIpMsrLast;
3373 uint32_t idLbrTosMsr;
3374
3375 /*
3376 * Determine the LBR MSRs supported for this host CPU family and model.
3377 *
3378 * See Intel spec. 17.4.8 "LBR Stack".
3379 * See Intel "Model-Specific Registers" spec.
3380 */
3381 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3382 | pVM->cpum.ro.HostFeatures.uModel;
3383 switch (uFamilyModel)
3384 {
3385 case 0x0f01: case 0x0f02:
3386 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3387 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3388 idLbrToIpMsrFirst = 0x0;
3389 idLbrToIpMsrLast = 0x0;
3390 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3391 break;
3392
3393 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3394 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3395 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3396 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3397 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3398 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3399 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3400 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3401 break;
3402
3403 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3404 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3405 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3406 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3407 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3408 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3409 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3410 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3411 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3412 break;
3413
3414 case 0x0617: case 0x061d: case 0x060f:
3415 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3416 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3417 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3418 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3419 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3420 break;
3421
3422 /* Atom and related microarchitectures we don't care about:
3423 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3424 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3425 case 0x0636: */
3426 /* All other CPUs: */
3427 default:
3428 {
3429 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3430 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3431 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3432 }
3433 }
3434
3435 /*
3436 * Validate.
3437 */
3438 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3439 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3440 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3441 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3442 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3443 {
3444 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3445 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3446 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3447 }
3448 NOREF(pVCpu0);
3449
3450 /*
3451 * Update the LBR info. to the VM struct. for use later.
3452 */
3453 pVM->hm.s.vmx.idLbrTosMsr = idLbrTosMsr;
3454 pVM->hm.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3455 pVM->hm.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3456
3457 pVM->hm.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3458 pVM->hm.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3459 return VINF_SUCCESS;
3460}
3461
3462
3463#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3464/**
3465 * Sets up the shadow VMCS fields arrays.
3466 *
3467 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3468 * executing the guest.
3469 *
3470 * @returns VBox status code.
3471 * @param pVM The cross context VM structure.
3472 */
3473static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3474{
3475 /*
3476 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3477 * when the host does not support it.
3478 */
3479 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3480 if ( !fGstVmwriteAll
3481 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3482 { /* likely. */ }
3483 else
3484 {
3485 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3486 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3487 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3488 }
3489
3490 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3491 uint32_t cRwFields = 0;
3492 uint32_t cRoFields = 0;
3493 for (uint32_t i = 0; i < cVmcsFields; i++)
3494 {
3495 VMXVMCSFIELD VmcsField;
3496 VmcsField.u = g_aVmcsFields[i];
3497
3498 /*
3499 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3500 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3501 * in the shadow VMCS fields array as they would be redundant.
3502 *
3503 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3504 * we must not include it in the shadow VMCS fields array. Guests attempting to
3505 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3506 * the required behavior.
3507 */
3508 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3509 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3510 {
3511 /*
3512 * Read-only fields are placed in a separate array so that while syncing shadow
3513 * VMCS fields later (which is more performance critical) we can avoid branches.
3514 *
3515 * However, if the guest can write to all fields (including read-only fields),
3516 * we treat it a as read/write field. Otherwise, writing to these fields would
3517 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3518 */
3519 if ( fGstVmwriteAll
3520 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3521 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3522 else
3523 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3524 }
3525 }
3526
3527 /* Update the counts. */
3528 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3529 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3530 return VINF_SUCCESS;
3531}
3532
3533
3534/**
3535 * Sets up the VMREAD and VMWRITE bitmaps.
3536 *
3537 * @param pVM The cross context VM structure.
3538 */
3539static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3540{
3541 /*
3542 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3543 */
3544 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3545 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3546 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3547 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3548 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3549
3550 /*
3551 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3552 * VMREAD and VMWRITE bitmaps.
3553 */
3554 {
3555 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3556 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3557 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3558 {
3559 uint32_t const uVmcsField = paShadowVmcsFields[i];
3560 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3561 Assert(uVmcsField >> 3 < cbBitmap);
3562 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3563 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3564 }
3565 }
3566
3567 /*
3568 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3569 * if the host supports VMWRITE to all supported VMCS fields.
3570 */
3571 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3572 {
3573 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3574 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3575 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3576 {
3577 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3578 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3579 Assert(uVmcsField >> 3 < cbBitmap);
3580 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3581 }
3582 }
3583}
3584#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3585
3586
3587/**
3588 * Sets up the virtual-APIC page address for the VMCS.
3589 *
3590 * @param pVmcsInfo The VMCS info. object.
3591 */
3592DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3593{
3594 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3595 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3596 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3597 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3598 AssertRC(rc);
3599}
3600
3601
3602/**
3603 * Sets up the MSR-bitmap address for the VMCS.
3604 *
3605 * @param pVmcsInfo The VMCS info. object.
3606 */
3607DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3608{
3609 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3610 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3611 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3612 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3613 AssertRC(rc);
3614}
3615
3616
3617/**
3618 * Sets up the APIC-access page address for the VMCS.
3619 *
3620 * @param pVCpu The cross context virtual CPU structure.
3621 */
3622DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3623{
3624 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3625 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3626 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3627 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3628 AssertRC(rc);
3629}
3630
3631
3632#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3633/**
3634 * Sets up the VMREAD bitmap address for the VMCS.
3635 *
3636 * @param pVCpu The cross context virtual CPU structure.
3637 */
3638DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3639{
3640 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3641 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3642 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3643 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3644 AssertRC(rc);
3645}
3646
3647
3648/**
3649 * Sets up the VMWRITE bitmap address for the VMCS.
3650 *
3651 * @param pVCpu The cross context virtual CPU structure.
3652 */
3653DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3654{
3655 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3656 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3657 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3658 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3659 AssertRC(rc);
3660}
3661#endif
3662
3663
3664/**
3665 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3666 * in the VMCS.
3667 *
3668 * @returns VBox status code.
3669 * @param pVmcsInfo The VMCS info. object.
3670 */
3671DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3672{
3673 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3674 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3675 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3676
3677 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3678 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3679 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3680
3681 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3682 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3683 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3684
3685 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3686 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3687 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3688 return VINF_SUCCESS;
3689}
3690
3691
3692/**
3693 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3694 *
3695 * @param pVCpu The cross context virtual CPU structure.
3696 * @param pVmcsInfo The VMCS info. object.
3697 */
3698static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3699{
3700 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3701
3702 /*
3703 * By default, ensure guest attempts to access any MSR cause VM-exits.
3704 * This shall later be relaxed for specific MSRs as necessary.
3705 *
3706 * Note: For nested-guests, the entire bitmap will be merged prior to
3707 * executing the nested-guest using hardware-assisted VMX and hence there
3708 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3709 */
3710 Assert(pVmcsInfo->pvMsrBitmap);
3711 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3712
3713 /*
3714 * The guest can access the following MSRs (read, write) without causing
3715 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3716 */
3717 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3718 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3719 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3720 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3721 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3722 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3723
3724 /*
3725 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3726 * associated with then. We never need to intercept access (writes need to be
3727 * executed without causing a VM-exit, reads will #GP fault anyway).
3728 *
3729 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3730 * read/write them. We swap the the guest/host MSR value using the
3731 * auto-load/store MSR area.
3732 */
3733 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3734 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3735 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3736 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3737 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3738 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3739
3740 /*
3741 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3742 * required for 64-bit guests.
3743 */
3744 if (pVM->hm.s.fAllow64BitGuests)
3745 {
3746 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3747 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3748 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3749 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3750 }
3751
3752 /*
3753 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3754 */
3755#ifdef VBOX_STRICT
3756 Assert(pVmcsInfo->pvMsrBitmap);
3757 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3758 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3759#endif
3760}
3761
3762
3763/**
3764 * Sets up pin-based VM-execution controls in the VMCS.
3765 *
3766 * @returns VBox status code.
3767 * @param pVCpu The cross context virtual CPU structure.
3768 * @param pVmcsInfo The VMCS info. object.
3769 */
3770static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3771{
3772 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3773 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3774 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3775
3776 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3777 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3778
3779 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3780 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3781
3782 /* Enable the VMX-preemption timer. */
3783 if (pVM->hm.s.vmx.fUsePreemptTimer)
3784 {
3785 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3786 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3787 }
3788
3789#if 0
3790 /* Enable posted-interrupt processing. */
3791 if (pVM->hm.s.fPostedIntrs)
3792 {
3793 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3794 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3795 fVal |= VMX_PIN_CTLS_POSTED_INT;
3796 }
3797#endif
3798
3799 if ((fVal & fZap) != fVal)
3800 {
3801 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3802 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3803 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3804 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3805 }
3806
3807 /* Commit it to the VMCS and update our cache. */
3808 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3809 AssertRC(rc);
3810 pVmcsInfo->u32PinCtls = fVal;
3811
3812 return VINF_SUCCESS;
3813}
3814
3815
3816/**
3817 * Sets up secondary processor-based VM-execution controls in the VMCS.
3818 *
3819 * @returns VBox status code.
3820 * @param pVCpu The cross context virtual CPU structure.
3821 * @param pVmcsInfo The VMCS info. object.
3822 */
3823static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3824{
3825 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3826 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3827 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3828
3829 /* WBINVD causes a VM-exit. */
3830 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3831 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3832
3833 /* Enable EPT (aka nested-paging). */
3834 if (pVM->hm.s.fNestedPaging)
3835 fVal |= VMX_PROC_CTLS2_EPT;
3836
3837 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3838 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3839 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3840 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3841 fVal |= VMX_PROC_CTLS2_INVPCID;
3842
3843 /* Enable VPID. */
3844 if (pVM->hm.s.vmx.fVpid)
3845 fVal |= VMX_PROC_CTLS2_VPID;
3846
3847 /* Enable unrestricted guest execution. */
3848 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3849 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3850
3851#if 0
3852 if (pVM->hm.s.fVirtApicRegs)
3853 {
3854 /* Enable APIC-register virtualization. */
3855 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3856 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3857
3858 /* Enable virtual-interrupt delivery. */
3859 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3860 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3861 }
3862#endif
3863
3864 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3865 where the TPR shadow resides. */
3866 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3867 * done dynamically. */
3868 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3869 {
3870 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3871 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3872 }
3873
3874 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3875 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3876 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3877 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3878 fVal |= VMX_PROC_CTLS2_RDTSCP;
3879
3880 /* Enable Pause-Loop exiting. */
3881 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3882 && pVM->hm.s.vmx.cPleGapTicks
3883 && pVM->hm.s.vmx.cPleWindowTicks)
3884 {
3885 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3886
3887 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3888 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3889 }
3890
3891 if ((fVal & fZap) != fVal)
3892 {
3893 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3894 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3895 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3896 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3897 }
3898
3899 /* Commit it to the VMCS and update our cache. */
3900 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3901 AssertRC(rc);
3902 pVmcsInfo->u32ProcCtls2 = fVal;
3903
3904 return VINF_SUCCESS;
3905}
3906
3907
3908/**
3909 * Sets up processor-based VM-execution controls in the VMCS.
3910 *
3911 * @returns VBox status code.
3912 * @param pVCpu The cross context virtual CPU structure.
3913 * @param pVmcsInfo The VMCS info. object.
3914 */
3915static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3916{
3917 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3918 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3919 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3920
3921 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3922 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3923 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3924 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3925 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3926 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3927 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3928
3929 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3930 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3931 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3932 {
3933 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3934 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3935 }
3936
3937 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3938 if (!pVM->hm.s.fNestedPaging)
3939 {
3940 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3941 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3942 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3943 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3944 }
3945
3946 /* Use TPR shadowing if supported by the CPU. */
3947 if ( PDMHasApic(pVM)
3948 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3949 {
3950 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3951 /* CR8 writes cause a VM-exit based on TPR threshold. */
3952 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3953 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3954 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3955 }
3956 else
3957 {
3958 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3959 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3960 if (pVM->hm.s.fAllow64BitGuests)
3961 {
3962 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3963 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3964 }
3965 }
3966
3967 /* Use MSR-bitmaps if supported by the CPU. */
3968 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3969 {
3970 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3971 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3972 }
3973
3974 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3975 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3976 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3977
3978 if ((fVal & fZap) != fVal)
3979 {
3980 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3981 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3982 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3983 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3984 }
3985
3986 /* Commit it to the VMCS and update our cache. */
3987 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3988 AssertRC(rc);
3989 pVmcsInfo->u32ProcCtls = fVal;
3990
3991 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3992 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3993 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3994
3995 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3996 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3997 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3998
3999 /* Sanity check, should not really happen. */
4000 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
4001 { /* likely */ }
4002 else
4003 {
4004 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4005 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4006 }
4007
4008 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4009 return VINF_SUCCESS;
4010}
4011
4012
4013/**
4014 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4015 * Processor-based VM-execution) control fields in the VMCS.
4016 *
4017 * @returns VBox status code.
4018 * @param pVCpu The cross context virtual CPU structure.
4019 * @param pVmcsInfo The VMCS info. object.
4020 */
4021static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4022{
4023#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4024 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
4025 {
4026 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4027 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4028 }
4029#endif
4030
4031 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4032 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4033 AssertRC(rc);
4034
4035 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4036 if (RT_SUCCESS(rc))
4037 {
4038 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4039 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4040
4041 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4042 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4043
4044 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4045 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4046
4047 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fLbr)
4048 {
4049 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4050 AssertRC(rc);
4051 }
4052 return VINF_SUCCESS;
4053 }
4054 else
4055 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4056 return rc;
4057}
4058
4059
4060/**
4061 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4062 *
4063 * We shall setup those exception intercepts that don't change during the
4064 * lifetime of the VM here. The rest are done dynamically while loading the
4065 * guest state.
4066 *
4067 * @param pVCpu The cross context virtual CPU structure.
4068 * @param pVmcsInfo The VMCS info. object.
4069 */
4070static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4071{
4072 /*
4073 * The following exceptions are always intercepted:
4074 *
4075 * #AC - To prevent the guest from hanging the CPU.
4076 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4077 * recursive #DBs can cause a CPU hang.
4078 * #PF - To sync our shadow page tables when nested-paging is not used.
4079 */
4080 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
4081 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4082 | RT_BIT(X86_XCPT_DB)
4083 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4084
4085 /* Commit it to the VMCS. */
4086 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4087 AssertRC(rc);
4088
4089 /* Update our cache of the exception bitmap. */
4090 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4091}
4092
4093
4094#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4095/**
4096 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4097 *
4098 * @returns VBox status code.
4099 * @param pVCpu The cross context virtual CPU structure.
4100 * @param pVmcsInfo The VMCS info. object.
4101 */
4102static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4103{
4104 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4105 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4106 AssertRC(rc);
4107
4108 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4109 if (RT_SUCCESS(rc))
4110 {
4111 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4112 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4113
4114 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4115 Assert(!pVmcsInfo->u64Cr0Mask);
4116 Assert(!pVmcsInfo->u64Cr4Mask);
4117 return VINF_SUCCESS;
4118 }
4119 else
4120 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4121 return rc;
4122}
4123#endif
4124
4125
4126/**
4127 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4128 * VMX.
4129 *
4130 * @returns VBox status code.
4131 * @param pVCpu The cross context virtual CPU structure.
4132 * @param pVmcsInfo The VMCS info. object.
4133 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4134 */
4135static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4136{
4137 Assert(pVmcsInfo->pvVmcs);
4138 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4139
4140 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4141 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4142 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4143 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4144
4145 LogFlowFunc(("\n"));
4146
4147 /*
4148 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4149 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4150 */
4151 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4152 if (RT_SUCCESS(rc))
4153 {
4154 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4155 if (RT_SUCCESS(rc))
4156 {
4157 if (!fIsNstGstVmcs)
4158 {
4159 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4160 if (RT_SUCCESS(rc))
4161 {
4162 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4163 if (RT_SUCCESS(rc))
4164 {
4165 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4166 if (RT_SUCCESS(rc))
4167 {
4168 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4169#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4170 /*
4171 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4172 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4173 * making it fit for use when VMCS shadowing is later enabled.
4174 */
4175 if (pVmcsInfo->pvShadowVmcs)
4176 {
4177 VMXVMCSREVID VmcsRevId;
4178 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4179 VmcsRevId.n.fIsShadowVmcs = 1;
4180 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4181 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4182 if (RT_SUCCESS(rc))
4183 { /* likely */ }
4184 else
4185 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4186 }
4187#endif
4188 }
4189 else
4190 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4191 }
4192 else
4193 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4194 }
4195 else
4196 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4197 }
4198 else
4199 {
4200#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4201 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4202 if (RT_SUCCESS(rc))
4203 { /* likely */ }
4204 else
4205 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4206#else
4207 AssertFailed();
4208#endif
4209 }
4210 }
4211 else
4212 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4213 }
4214 else
4215 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4216
4217 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4218 if (RT_SUCCESS(rc))
4219 {
4220 rc = hmR0VmxClearVmcs(pVmcsInfo);
4221 if (RT_SUCCESS(rc))
4222 { /* likely */ }
4223 else
4224 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4225 }
4226
4227 /*
4228 * Update the last-error record both for failures and success, so we
4229 * can propagate the status code back to ring-3 for diagnostics.
4230 */
4231 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4232 NOREF(pszVmcs);
4233 return rc;
4234}
4235
4236
4237/**
4238 * Does global VT-x initialization (called during module initialization).
4239 *
4240 * @returns VBox status code.
4241 */
4242VMMR0DECL(int) VMXR0GlobalInit(void)
4243{
4244#ifdef HMVMX_USE_FUNCTION_TABLE
4245 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4246# ifdef VBOX_STRICT
4247 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4248 Assert(g_apfnVMExitHandlers[i]);
4249# endif
4250#endif
4251 return VINF_SUCCESS;
4252}
4253
4254
4255/**
4256 * Does global VT-x termination (called during module termination).
4257 */
4258VMMR0DECL(void) VMXR0GlobalTerm()
4259{
4260 /* Nothing to do currently. */
4261}
4262
4263
4264/**
4265 * Sets up and activates VT-x on the current CPU.
4266 *
4267 * @returns VBox status code.
4268 * @param pHostCpu The HM physical-CPU structure.
4269 * @param pVM The cross context VM structure. Can be
4270 * NULL after a host resume operation.
4271 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4272 * fEnabledByHost is @c true).
4273 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4274 * @a fEnabledByHost is @c true).
4275 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4276 * enable VT-x on the host.
4277 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4278 */
4279VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4280 PCSUPHWVIRTMSRS pHwvirtMsrs)
4281{
4282 AssertPtr(pHostCpu);
4283 AssertPtr(pHwvirtMsrs);
4284 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4285
4286 /* Enable VT-x if it's not already enabled by the host. */
4287 if (!fEnabledByHost)
4288 {
4289 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4290 if (RT_FAILURE(rc))
4291 return rc;
4292 }
4293
4294 /*
4295 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4296 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4297 * invalidated when flushing by VPID.
4298 */
4299 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4300 {
4301 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4302 pHostCpu->fFlushAsidBeforeUse = false;
4303 }
4304 else
4305 pHostCpu->fFlushAsidBeforeUse = true;
4306
4307 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4308 ++pHostCpu->cTlbFlushes;
4309
4310 return VINF_SUCCESS;
4311}
4312
4313
4314/**
4315 * Deactivates VT-x on the current CPU.
4316 *
4317 * @returns VBox status code.
4318 * @param pHostCpu The HM physical-CPU structure.
4319 * @param pvCpuPage Pointer to the VMXON region.
4320 * @param HCPhysCpuPage Physical address of the VMXON region.
4321 *
4322 * @remarks This function should never be called when SUPR0EnableVTx() or
4323 * similar was used to enable VT-x on the host.
4324 */
4325VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4326{
4327 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4328
4329 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4330 return hmR0VmxLeaveRootMode(pHostCpu);
4331}
4332
4333
4334/**
4335 * Does per-VM VT-x initialization.
4336 *
4337 * @returns VBox status code.
4338 * @param pVM The cross context VM structure.
4339 */
4340VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4341{
4342 AssertPtr(pVM);
4343 LogFlowFunc(("pVM=%p\n", pVM));
4344
4345 hmR0VmxStructsInit(pVM);
4346 int rc = hmR0VmxStructsAlloc(pVM);
4347 if (RT_FAILURE(rc))
4348 {
4349 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4350 return rc;
4351 }
4352
4353 /* Setup the crash dump page. */
4354#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4355 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4356 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4357#endif
4358 return VINF_SUCCESS;
4359}
4360
4361
4362/**
4363 * Does per-VM VT-x termination.
4364 *
4365 * @returns VBox status code.
4366 * @param pVM The cross context VM structure.
4367 */
4368VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4369{
4370 AssertPtr(pVM);
4371 LogFlowFunc(("pVM=%p\n", pVM));
4372
4373#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4374 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4375 {
4376 Assert(pVM->hm.s.vmx.pvScratch);
4377 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4378 }
4379#endif
4380 hmR0VmxStructsFree(pVM);
4381 return VINF_SUCCESS;
4382}
4383
4384
4385/**
4386 * Sets up the VM for execution using hardware-assisted VMX.
4387 * This function is only called once per-VM during initialization.
4388 *
4389 * @returns VBox status code.
4390 * @param pVM The cross context VM structure.
4391 */
4392VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4393{
4394 AssertPtr(pVM);
4395 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4396
4397 LogFlowFunc(("pVM=%p\n", pVM));
4398
4399 /*
4400 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4401 * without causing a #GP.
4402 */
4403 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4404 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4405 { /* likely */ }
4406 else
4407 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4408
4409 /*
4410 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4411 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4412 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4413 */
4414 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4415 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4416 || !pVM->hm.s.vmx.pRealModeTSS))
4417 {
4418 LogRelFunc(("Invalid real-on-v86 state.\n"));
4419 return VERR_INTERNAL_ERROR;
4420 }
4421
4422 /* Initialize these always, see hmR3InitFinalizeR0().*/
4423 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4424 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4425
4426 /* Setup the tagged-TLB flush handlers. */
4427 int rc = hmR0VmxSetupTaggedTlb(pVM);
4428 if (RT_FAILURE(rc))
4429 {
4430 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4431 return rc;
4432 }
4433
4434 /* Determine LBR capabilities. */
4435 if (pVM->hm.s.vmx.fLbr)
4436 {
4437 rc = hmR0VmxSetupLbrMsrRange(pVM);
4438 if (RT_FAILURE(rc))
4439 {
4440 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4441 return rc;
4442 }
4443 }
4444
4445#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4446 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4447 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4448 {
4449 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4450 if (RT_SUCCESS(rc))
4451 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4452 else
4453 {
4454 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4455 return rc;
4456 }
4457 }
4458#endif
4459
4460 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4461 {
4462 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4463 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4464
4465 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4466 if (RT_SUCCESS(rc))
4467 {
4468#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4469 if (pVM->cpum.ro.GuestFeatures.fVmx)
4470 {
4471 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4472 if (RT_SUCCESS(rc))
4473 { /* likely */ }
4474 else
4475 {
4476 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4477 return rc;
4478 }
4479 }
4480#endif
4481 }
4482 else
4483 {
4484 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4485 return rc;
4486 }
4487 }
4488
4489 return VINF_SUCCESS;
4490}
4491
4492
4493/**
4494 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4495 * the VMCS.
4496 */
4497static void hmR0VmxExportHostControlRegs(void)
4498{
4499 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4500 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4501 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4502}
4503
4504
4505/**
4506 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4507 * the host-state area in the VMCS.
4508 *
4509 * @returns VBox status code.
4510 * @param pVCpu The cross context virtual CPU structure.
4511 */
4512static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4513{
4514/**
4515 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4516 * requirements. See hmR0VmxExportHostSegmentRegs().
4517 */
4518#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4519 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4520 { \
4521 bool fValidSelector = true; \
4522 if ((a_selValue) & X86_SEL_LDT) \
4523 { \
4524 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4525 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4526 } \
4527 if (fValidSelector) \
4528 { \
4529 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4530 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4531 } \
4532 (a_selValue) = 0; \
4533 }
4534
4535 /*
4536 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4537 * will be messed up. We should -not- save the messed up state without restoring
4538 * the original host-state, see @bugref{7240}.
4539 *
4540 * This apparently can happen (most likely the FPU changes), deal with it rather than
4541 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4542 */
4543 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4544 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4545 {
4546 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4547 pVCpu->idCpu));
4548 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4549 }
4550 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4551
4552 /*
4553 * Host segment registers.
4554 */
4555 RTSEL uSelES = ASMGetES();
4556 RTSEL uSelCS = ASMGetCS();
4557 RTSEL uSelSS = ASMGetSS();
4558 RTSEL uSelDS = ASMGetDS();
4559 RTSEL uSelFS = ASMGetFS();
4560 RTSEL uSelGS = ASMGetGS();
4561 RTSEL uSelTR = ASMGetTR();
4562
4563 /*
4564 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4565 * gain VM-entry and restore them before we get preempted.
4566 *
4567 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4568 */
4569 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4570 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4571 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4572 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4573
4574 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4575 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4576 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4577 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4578 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4579 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4580 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4581 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4582 Assert(uSelCS);
4583 Assert(uSelTR);
4584
4585 /* Write these host selector fields into the host-state area in the VMCS. */
4586 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4587 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4588 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4589 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4590 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4591 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4592 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4593
4594 /*
4595 * Host GDTR and IDTR.
4596 */
4597 RTGDTR Gdtr;
4598 RTIDTR Idtr;
4599 RT_ZERO(Gdtr);
4600 RT_ZERO(Idtr);
4601 ASMGetGDTR(&Gdtr);
4602 ASMGetIDTR(&Idtr);
4603 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4604 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4605
4606 /*
4607 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4608 * them to the maximum limit (0xffff) on every VM-exit.
4609 */
4610 if (Gdtr.cbGdt != 0xffff)
4611 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4612
4613 /*
4614 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4615 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4616 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4617 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4618 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4619 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4620 * at 0xffff on hosts where we are sure it won't cause trouble.
4621 */
4622#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4623 if (Idtr.cbIdt < 0x0fff)
4624#else
4625 if (Idtr.cbIdt != 0xffff)
4626#endif
4627 {
4628 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4629 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4630 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4631 }
4632
4633 /*
4634 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4635 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4636 * RPL should be too in most cases.
4637 */
4638 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4639 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4640
4641 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4642 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4643
4644 /*
4645 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4646 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4647 * restoration if the host has something else. Task switching is not supported in 64-bit
4648 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4649 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4650 *
4651 * [1] See Intel spec. 3.5 "System Descriptor Types".
4652 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4653 */
4654 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4655 Assert(pDesc->System.u4Type == 11);
4656 if ( pDesc->System.u16LimitLow != 0x67
4657 || pDesc->System.u4LimitHigh)
4658 {
4659 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4660 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4661 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4662 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4663 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4664 }
4665
4666 /*
4667 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4668 */
4669 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4670 {
4671 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4672 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4673 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4674 {
4675 /* The GDT is read-only but the writable GDT is available. */
4676 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4677 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4678 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4679 AssertRCReturn(rc, rc);
4680 }
4681 }
4682
4683 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4684 AssertRC(rc);
4685
4686 /*
4687 * Host FS base and GS base.
4688 */
4689 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4690 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4691 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4692 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4693
4694 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4695 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4696 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4697 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4698 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4699
4700 return VINF_SUCCESS;
4701#undef VMXLOCAL_ADJUST_HOST_SEG
4702}
4703
4704
4705/**
4706 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4707 * host-state area of the VMCS.
4708 *
4709 * These MSRs will be automatically restored on the host after every successful
4710 * VM-exit.
4711 *
4712 * @param pVCpu The cross context virtual CPU structure.
4713 *
4714 * @remarks No-long-jump zone!!!
4715 */
4716static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4717{
4718 AssertPtr(pVCpu);
4719
4720 /*
4721 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4722 * rather than swapping them on every VM-entry.
4723 */
4724 hmR0VmxLazySaveHostMsrs(pVCpu);
4725
4726 /*
4727 * Host Sysenter MSRs.
4728 */
4729 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4730 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4731 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4732
4733 /*
4734 * Host EFER MSR.
4735 *
4736 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4737 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4738 */
4739 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4740 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4741 {
4742 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4743 AssertRC(rc);
4744 }
4745
4746 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4747 * hmR0VmxExportGuestEntryExitCtls(). */
4748}
4749
4750
4751/**
4752 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4753 *
4754 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4755 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4756 *
4757 * @returns true if we need to load guest EFER, false otherwise.
4758 * @param pVCpu The cross context virtual CPU structure.
4759 * @param pVmxTransient The VMX-transient structure.
4760 *
4761 * @remarks Requires EFER, CR4.
4762 * @remarks No-long-jump zone!!!
4763 */
4764static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4765{
4766#ifdef HMVMX_ALWAYS_SWAP_EFER
4767 RT_NOREF2(pVCpu, pVmxTransient);
4768 return true;
4769#else
4770 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4771 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4772 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4773 uint64_t const u64GuestEfer = pCtx->msrEFER;
4774
4775# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4776 /*
4777 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4778 * the nested-guest.
4779 */
4780 if ( pVmxTransient->fIsNestedGuest
4781 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4782 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4783 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4784 return true;
4785# else
4786 RT_NOREF(pVmxTransient);
4787#endif
4788
4789 /*
4790 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4791 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4792 */
4793 if ( CPUMIsGuestInLongModeEx(pCtx)
4794 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4795 return true;
4796
4797 /*
4798 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4799 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4800 *
4801 * See Intel spec. 4.5 "IA-32e Paging".
4802 * See Intel spec. 4.1.1 "Three Paging Modes".
4803 *
4804 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4805 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4806 */
4807 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4808 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4809 if ( (pCtx->cr4 & X86_CR4_PAE)
4810 && (pCtx->cr0 & X86_CR0_PG))
4811 {
4812 /*
4813 * If nested paging is not used, verify that the guest paging mode matches the
4814 * shadow paging mode which is/will be placed in the VMCS (which is what will
4815 * actually be used while executing the guest and not the CR4 shadow value).
4816 */
4817 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4818 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4819 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4820 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4821 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4822 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4823 {
4824 /* Verify that the host is NX capable. */
4825 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4826 return true;
4827 }
4828 }
4829
4830 return false;
4831#endif
4832}
4833
4834
4835/**
4836 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4837 * VMCS.
4838 *
4839 * This is typically required when the guest changes paging mode.
4840 *
4841 * @returns VBox status code.
4842 * @param pVCpu The cross context virtual CPU structure.
4843 * @param pVmxTransient The VMX-transient structure.
4844 *
4845 * @remarks Requires EFER.
4846 * @remarks No-long-jump zone!!!
4847 */
4848static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4849{
4850 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4851 {
4852 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4853 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4854 bool const fGstInLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
4855
4856 /*
4857 * VMRUN function.
4858 * If the guest is in long mode, use the 64-bit guest handler, else the 32-bit guest handler.
4859 * The host is always 64-bit since we no longer support 32-bit hosts.
4860 */
4861 if (fGstInLongMode)
4862 {
4863#ifndef VBOX_WITH_64_BITS_GUESTS
4864 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
4865#else
4866 Assert(pVM->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
4867 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4868#endif
4869 }
4870 else
4871 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4872
4873 /*
4874 * VM-entry controls.
4875 */
4876 {
4877 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4878 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4879
4880 /*
4881 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4882 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4883 *
4884 * For nested-guests, this is a mandatory VM-entry control. It's also
4885 * required because we do not want to leak host bits to the nested-guest.
4886 */
4887 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4888
4889 /*
4890 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4891 *
4892 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4893 * required to get the nested-guest working with hardware-assisted VMX execution.
4894 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4895 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4896 * here rather than while merging the guest VMCS controls.
4897 */
4898 if (fGstInLongMode)
4899 {
4900 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4901 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4902 }
4903 else
4904 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4905
4906 /*
4907 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4908 *
4909 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4910 * regardless of whether the nested-guest VMCS specifies it because we are free to
4911 * load whatever MSRs we require and we do not need to modify the guest visible copy
4912 * of the VM-entry MSR load area.
4913 */
4914 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4915 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4916 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4917 else
4918 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4919
4920 /*
4921 * The following should -not- be set (since we're not in SMM mode):
4922 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4923 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4924 */
4925
4926 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4927 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4928
4929 if ((fVal & fZap) == fVal)
4930 { /* likely */ }
4931 else
4932 {
4933 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4934 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4935 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4936 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4937 }
4938
4939 /* Commit it to the VMCS. */
4940 if (pVmcsInfo->u32EntryCtls != fVal)
4941 {
4942 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4943 AssertRC(rc);
4944 pVmcsInfo->u32EntryCtls = fVal;
4945 }
4946 }
4947
4948 /*
4949 * VM-exit controls.
4950 */
4951 {
4952 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4953 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4954
4955 /*
4956 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4957 * supported the 1-setting of this bit.
4958 *
4959 * For nested-guests, we set the "save debug controls" as the converse
4960 * "load debug controls" is mandatory for nested-guests anyway.
4961 */
4962 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4963
4964 /*
4965 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4966 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4967 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4968 * hmR0VmxExportHostMsrs().
4969 *
4970 * For nested-guests, we always set this bit as we do not support 32-bit
4971 * hosts.
4972 */
4973 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4974
4975 /*
4976 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4977 *
4978 * For nested-guests, we should use the "save IA32_EFER" control if we also
4979 * used the "load IA32_EFER" control while exporting VM-entry controls.
4980 */
4981 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4982 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4983 {
4984 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4985 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4986 }
4987
4988 /*
4989 * Enable saving of the VMX-preemption timer value on VM-exit.
4990 * For nested-guests, currently not exposed/used.
4991 */
4992 if ( pVM->hm.s.vmx.fUsePreemptTimer
4993 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4994 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4995
4996 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4997 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4998
4999 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5000 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5001 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5002
5003 if ((fVal & fZap) == fVal)
5004 { /* likely */ }
5005 else
5006 {
5007 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5008 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5009 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5010 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5011 }
5012
5013 /* Commit it to the VMCS. */
5014 if (pVmcsInfo->u32ExitCtls != fVal)
5015 {
5016 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5017 AssertRC(rc);
5018 pVmcsInfo->u32ExitCtls = fVal;
5019 }
5020 }
5021
5022 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5023 }
5024 return VINF_SUCCESS;
5025}
5026
5027
5028/**
5029 * Sets the TPR threshold in the VMCS.
5030 *
5031 * @param pVmcsInfo The VMCS info. object.
5032 * @param u32TprThreshold The TPR threshold (task-priority class only).
5033 */
5034DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5035{
5036 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5037 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5038 RT_NOREF(pVmcsInfo);
5039 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5040 AssertRC(rc);
5041}
5042
5043
5044/**
5045 * Exports the guest APIC TPR state into the VMCS.
5046 *
5047 * @param pVCpu The cross context virtual CPU structure.
5048 * @param pVmxTransient The VMX-transient structure.
5049 *
5050 * @remarks No-long-jump zone!!!
5051 */
5052static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5053{
5054 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5055 {
5056 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5057
5058 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5059 if (!pVmxTransient->fIsNestedGuest)
5060 {
5061 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5062 && APICIsEnabled(pVCpu))
5063 {
5064 /*
5065 * Setup TPR shadowing.
5066 */
5067 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5068 {
5069 bool fPendingIntr = false;
5070 uint8_t u8Tpr = 0;
5071 uint8_t u8PendingIntr = 0;
5072 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5073 AssertRC(rc);
5074
5075 /*
5076 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5077 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5078 * priority of the pending interrupt so we can deliver the interrupt. If there
5079 * are no interrupts pending, set threshold to 0 to not cause any
5080 * TPR-below-threshold VM-exits.
5081 */
5082 uint32_t u32TprThreshold = 0;
5083 if (fPendingIntr)
5084 {
5085 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5086 (which is the Task-Priority Class). */
5087 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5088 const uint8_t u8TprPriority = u8Tpr >> 4;
5089 if (u8PendingPriority <= u8TprPriority)
5090 u32TprThreshold = u8PendingPriority;
5091 }
5092
5093 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5094 }
5095 }
5096 }
5097 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5098 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5099 }
5100}
5101
5102
5103/**
5104 * Gets the guest interruptibility-state and updates related force-flags.
5105 *
5106 * @returns Guest's interruptibility-state.
5107 * @param pVCpu The cross context virtual CPU structure.
5108 *
5109 * @remarks No-long-jump zone!!!
5110 */
5111static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5112{
5113 /*
5114 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5115 */
5116 uint32_t fIntrState = 0;
5117 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5118 {
5119 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5120 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5121
5122 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5123 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5124 {
5125 if (pCtx->eflags.Bits.u1IF)
5126 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5127 else
5128 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5129 }
5130 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5131 {
5132 /*
5133 * We can clear the inhibit force flag as even if we go back to the recompiler
5134 * without executing guest code in VT-x, the flag's condition to be cleared is
5135 * met and thus the cleared state is correct.
5136 */
5137 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5138 }
5139 }
5140
5141 /*
5142 * Check if we should inhibit NMI delivery.
5143 */
5144 if (CPUMIsGuestNmiBlocking(pVCpu))
5145 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5146
5147 /*
5148 * Validate.
5149 */
5150#ifdef VBOX_STRICT
5151 /* We don't support block-by-SMI yet.*/
5152 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5153
5154 /* Block-by-STI must not be set when interrupts are disabled. */
5155 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5156 {
5157 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5158 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5159 }
5160#endif
5161
5162 return fIntrState;
5163}
5164
5165
5166/**
5167 * Exports the exception intercepts required for guest execution in the VMCS.
5168 *
5169 * @param pVCpu The cross context virtual CPU structure.
5170 * @param pVmxTransient The VMX-transient structure.
5171 *
5172 * @remarks No-long-jump zone!!!
5173 */
5174static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5175{
5176 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5177 {
5178 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5179 if ( !pVmxTransient->fIsNestedGuest
5180 && pVCpu->hm.s.fGIMTrapXcptUD)
5181 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5182 else
5183 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5184
5185 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5186 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5187 }
5188}
5189
5190
5191/**
5192 * Exports the guest's RIP into the guest-state area in the VMCS.
5193 *
5194 * @param pVCpu The cross context virtual CPU structure.
5195 *
5196 * @remarks No-long-jump zone!!!
5197 */
5198static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5199{
5200 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5201 {
5202 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5203
5204 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5205 AssertRC(rc);
5206
5207 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5208 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5209 }
5210}
5211
5212
5213/**
5214 * Exports the guest's RSP into the guest-state area in the VMCS.
5215 *
5216 * @param pVCpu The cross context virtual CPU structure.
5217 *
5218 * @remarks No-long-jump zone!!!
5219 */
5220static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5221{
5222 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5223 {
5224 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5225
5226 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5227 AssertRC(rc);
5228
5229 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5230 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5231 }
5232}
5233
5234
5235/**
5236 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5237 *
5238 * @param pVCpu The cross context virtual CPU structure.
5239 * @param pVmxTransient The VMX-transient structure.
5240 *
5241 * @remarks No-long-jump zone!!!
5242 */
5243static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5244{
5245 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5246 {
5247 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5248
5249 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5250 Let us assert it as such and use 32-bit VMWRITE. */
5251 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5252 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5253 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5254 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5255
5256 /*
5257 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5258 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5259 * can run the real-mode guest code under Virtual 8086 mode.
5260 */
5261 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5262 if (pVmcsInfo->RealMode.fRealOnV86Active)
5263 {
5264 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5265 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5266 Assert(!pVmxTransient->fIsNestedGuest);
5267 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5268 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5269 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5270 }
5271
5272 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5273 AssertRC(rc);
5274
5275 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5276 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5277 }
5278}
5279
5280
5281#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5282/**
5283 * Copies the nested-guest VMCS to the shadow VMCS.
5284 *
5285 * @returns VBox status code.
5286 * @param pVCpu The cross context virtual CPU structure.
5287 * @param pVmcsInfo The VMCS info. object.
5288 *
5289 * @remarks No-long-jump zone!!!
5290 */
5291static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5292{
5293 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5294 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5295
5296 /*
5297 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5298 * current VMCS, as we may try saving guest lazy MSRs.
5299 *
5300 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5301 * calling the import VMCS code which is currently performing the guest MSR reads
5302 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5303 * and the rest of the VMX leave session machinery.
5304 */
5305 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5306
5307 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5308 if (RT_SUCCESS(rc))
5309 {
5310 /*
5311 * Copy all guest read/write VMCS fields.
5312 *
5313 * We don't check for VMWRITE failures here for performance reasons and
5314 * because they are not expected to fail, barring irrecoverable conditions
5315 * like hardware errors.
5316 */
5317 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5318 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5319 {
5320 uint64_t u64Val;
5321 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5322 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5323 VMXWriteVmcs64(uVmcsField, u64Val);
5324 }
5325
5326 /*
5327 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5328 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5329 */
5330 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5331 {
5332 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5333 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5334 {
5335 uint64_t u64Val;
5336 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5337 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5338 VMXWriteVmcs64(uVmcsField, u64Val);
5339 }
5340 }
5341
5342 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5343 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5344 }
5345
5346 ASMSetFlags(fEFlags);
5347 return rc;
5348}
5349
5350
5351/**
5352 * Copies the shadow VMCS to the nested-guest VMCS.
5353 *
5354 * @returns VBox status code.
5355 * @param pVCpu The cross context virtual CPU structure.
5356 * @param pVmcsInfo The VMCS info. object.
5357 *
5358 * @remarks Called with interrupts disabled.
5359 */
5360static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5361{
5362 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5363 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5364 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5365
5366 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5367 if (RT_SUCCESS(rc))
5368 {
5369 /*
5370 * Copy guest read/write fields from the shadow VMCS.
5371 * Guest read-only fields cannot be modified, so no need to copy them.
5372 *
5373 * We don't check for VMREAD failures here for performance reasons and
5374 * because they are not expected to fail, barring irrecoverable conditions
5375 * like hardware errors.
5376 */
5377 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5378 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5379 {
5380 uint64_t u64Val;
5381 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5382 VMXReadVmcs64(uVmcsField, &u64Val);
5383 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5384 }
5385
5386 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5387 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5388 }
5389 return rc;
5390}
5391
5392
5393/**
5394 * Enables VMCS shadowing for the given VMCS info. object.
5395 *
5396 * @param pVmcsInfo The VMCS info. object.
5397 *
5398 * @remarks No-long-jump zone!!!
5399 */
5400static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5401{
5402 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5403 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5404 {
5405 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5406 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5407 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5408 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5409 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5410 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5411 Log4Func(("Enabled\n"));
5412 }
5413}
5414
5415
5416/**
5417 * Disables VMCS shadowing for the given VMCS info. object.
5418 *
5419 * @param pVmcsInfo The VMCS info. object.
5420 *
5421 * @remarks No-long-jump zone!!!
5422 */
5423static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5424{
5425 /*
5426 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5427 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5428 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5429 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5430 *
5431 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5432 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5433 */
5434 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5435 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5436 {
5437 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5438 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5439 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5440 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5441 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5442 Log4Func(("Disabled\n"));
5443 }
5444}
5445#endif
5446
5447
5448/**
5449 * Exports the guest hardware-virtualization state.
5450 *
5451 * @returns VBox status code.
5452 * @param pVCpu The cross context virtual CPU structure.
5453 * @param pVmxTransient The VMX-transient structure.
5454 *
5455 * @remarks No-long-jump zone!!!
5456 */
5457static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5458{
5459 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5460 {
5461#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5462 /*
5463 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5464 * VMCS shadowing.
5465 */
5466 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5467 {
5468 /*
5469 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5470 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5471 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5472 *
5473 * We check for VMX root mode here in case the guest executes VMXOFF without
5474 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5475 * not clear the current VMCS pointer.
5476 */
5477 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5478 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5479 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5480 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5481 {
5482 /* Paranoia. */
5483 Assert(!pVmxTransient->fIsNestedGuest);
5484
5485 /*
5486 * For performance reasons, also check if the nested hypervisor's current VMCS
5487 * was newly loaded or modified before copying it to the shadow VMCS.
5488 */
5489 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5490 {
5491 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5492 AssertRCReturn(rc, rc);
5493 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5494 }
5495 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5496 }
5497 else
5498 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5499 }
5500#else
5501 NOREF(pVmxTransient);
5502#endif
5503 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5504 }
5505 return VINF_SUCCESS;
5506}
5507
5508
5509/**
5510 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5511 *
5512 * The guest FPU state is always pre-loaded hence we don't need to bother about
5513 * sharing FPU related CR0 bits between the guest and host.
5514 *
5515 * @returns VBox status code.
5516 * @param pVCpu The cross context virtual CPU structure.
5517 * @param pVmxTransient The VMX-transient structure.
5518 *
5519 * @remarks No-long-jump zone!!!
5520 */
5521static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5522{
5523 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5524 {
5525 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5526 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5527
5528 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5529 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5530 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5531 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5532 else
5533 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5534
5535 if (!pVmxTransient->fIsNestedGuest)
5536 {
5537 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5538 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5539 uint64_t const u64ShadowCr0 = u64GuestCr0;
5540 Assert(!RT_HI_U32(u64GuestCr0));
5541
5542 /*
5543 * Setup VT-x's view of the guest CR0.
5544 */
5545 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5546 if (pVM->hm.s.fNestedPaging)
5547 {
5548 if (CPUMIsGuestPagingEnabled(pVCpu))
5549 {
5550 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5551 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5552 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5553 }
5554 else
5555 {
5556 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5557 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5558 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5559 }
5560
5561 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5562 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5563 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5564 }
5565 else
5566 {
5567 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5568 u64GuestCr0 |= X86_CR0_WP;
5569 }
5570
5571 /*
5572 * Guest FPU bits.
5573 *
5574 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5575 * using CR0.TS.
5576 *
5577 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5578 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5579 */
5580 u64GuestCr0 |= X86_CR0_NE;
5581
5582 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5583 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5584
5585 /*
5586 * Update exception intercepts.
5587 */
5588 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5589 if (pVmcsInfo->RealMode.fRealOnV86Active)
5590 {
5591 Assert(PDMVmmDevHeapIsEnabled(pVM));
5592 Assert(pVM->hm.s.vmx.pRealModeTSS);
5593 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5594 }
5595 else
5596 {
5597 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5598 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5599 if (fInterceptMF)
5600 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5601 }
5602
5603 /* Additional intercepts for debugging, define these yourself explicitly. */
5604#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5605 uXcptBitmap |= 0
5606 | RT_BIT(X86_XCPT_BP)
5607 | RT_BIT(X86_XCPT_DE)
5608 | RT_BIT(X86_XCPT_NM)
5609 | RT_BIT(X86_XCPT_TS)
5610 | RT_BIT(X86_XCPT_UD)
5611 | RT_BIT(X86_XCPT_NP)
5612 | RT_BIT(X86_XCPT_SS)
5613 | RT_BIT(X86_XCPT_GP)
5614 | RT_BIT(X86_XCPT_PF)
5615 | RT_BIT(X86_XCPT_MF)
5616 ;
5617#elif defined(HMVMX_ALWAYS_TRAP_PF)
5618 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5619#endif
5620 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5621 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5622 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5623
5624 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5625 u64GuestCr0 |= fSetCr0;
5626 u64GuestCr0 &= fZapCr0;
5627 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5628
5629 /* Commit the CR0 and related fields to the guest VMCS. */
5630 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5631 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5632 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5633 {
5634 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5635 AssertRC(rc);
5636 }
5637 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5638 {
5639 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5640 AssertRC(rc);
5641 }
5642
5643 /* Update our caches. */
5644 pVmcsInfo->u32ProcCtls = uProcCtls;
5645 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5646
5647 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5648 }
5649 else
5650 {
5651 /*
5652 * With nested-guests, we may have extended the guest/host mask here since we
5653 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5654 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5655 * originally supplied. We must copy those bits from the nested-guest CR0 into
5656 * the nested-guest CR0 read-shadow.
5657 */
5658 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5659 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5660 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5661 Assert(!RT_HI_U32(u64GuestCr0));
5662 Assert(u64GuestCr0 & X86_CR0_NE);
5663
5664 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5665 u64GuestCr0 |= fSetCr0;
5666 u64GuestCr0 &= fZapCr0;
5667 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5668
5669 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5670 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5671 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5672
5673 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5674 }
5675
5676 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5677 }
5678
5679 return VINF_SUCCESS;
5680}
5681
5682
5683/**
5684 * Exports the guest control registers (CR3, CR4) into the guest-state area
5685 * in the VMCS.
5686 *
5687 * @returns VBox strict status code.
5688 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5689 * without unrestricted guest access and the VMMDev is not presently
5690 * mapped (e.g. EFI32).
5691 *
5692 * @param pVCpu The cross context virtual CPU structure.
5693 * @param pVmxTransient The VMX-transient structure.
5694 *
5695 * @remarks No-long-jump zone!!!
5696 */
5697static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5698{
5699 int rc = VINF_SUCCESS;
5700 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5701
5702 /*
5703 * Guest CR2.
5704 * It's always loaded in the assembler code. Nothing to do here.
5705 */
5706
5707 /*
5708 * Guest CR3.
5709 */
5710 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5711 {
5712 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5713
5714 if (pVM->hm.s.fNestedPaging)
5715 {
5716 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5717 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5718
5719 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5720 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5721 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5722 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5723
5724 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5725 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5726 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5727
5728 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5729 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5730 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5731 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5732 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5733 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5734 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5735
5736 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5737 AssertRC(rc);
5738
5739 uint64_t u64GuestCr3;
5740 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5741 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5742 || CPUMIsGuestPagingEnabledEx(pCtx))
5743 {
5744 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5745 if (CPUMIsGuestInPAEModeEx(pCtx))
5746 {
5747 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5748 AssertRC(rc);
5749 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5750 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5751 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5752 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5753 }
5754
5755 /*
5756 * The guest's view of its CR3 is unblemished with nested paging when the
5757 * guest is using paging or we have unrestricted guest execution to handle
5758 * the guest when it's not using paging.
5759 */
5760 u64GuestCr3 = pCtx->cr3;
5761 }
5762 else
5763 {
5764 /*
5765 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5766 * thinks it accesses physical memory directly, we use our identity-mapped
5767 * page table to map guest-linear to guest-physical addresses. EPT takes care
5768 * of translating it to host-physical addresses.
5769 */
5770 RTGCPHYS GCPhys;
5771 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5772
5773 /* We obtain it here every time as the guest could have relocated this PCI region. */
5774 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5775 if (RT_SUCCESS(rc))
5776 { /* likely */ }
5777 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5778 {
5779 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5780 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5781 }
5782 else
5783 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5784
5785 u64GuestCr3 = GCPhys;
5786 }
5787
5788 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5789 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5790 AssertRC(rc);
5791 }
5792 else
5793 {
5794 Assert(!pVmxTransient->fIsNestedGuest);
5795 /* Non-nested paging case, just use the hypervisor's CR3. */
5796 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5797
5798 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5799 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5800 AssertRC(rc);
5801 }
5802
5803 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5804 }
5805
5806 /*
5807 * Guest CR4.
5808 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5809 */
5810 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5811 {
5812 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5813 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5814
5815 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5816 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5817
5818 /*
5819 * With nested-guests, we may have extended the guest/host mask here (since we
5820 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5821 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5822 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5823 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5824 */
5825 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5826 uint64_t u64GuestCr4 = pCtx->cr4;
5827 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5828 ? pCtx->cr4
5829 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5830 Assert(!RT_HI_U32(u64GuestCr4));
5831
5832 /*
5833 * Setup VT-x's view of the guest CR4.
5834 *
5835 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5836 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5837 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5838 *
5839 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5840 */
5841 if (pVmcsInfo->RealMode.fRealOnV86Active)
5842 {
5843 Assert(pVM->hm.s.vmx.pRealModeTSS);
5844 Assert(PDMVmmDevHeapIsEnabled(pVM));
5845 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5846 }
5847
5848 if (pVM->hm.s.fNestedPaging)
5849 {
5850 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5851 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5852 {
5853 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5854 u64GuestCr4 |= X86_CR4_PSE;
5855 /* Our identity mapping is a 32-bit page directory. */
5856 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5857 }
5858 /* else use guest CR4.*/
5859 }
5860 else
5861 {
5862 Assert(!pVmxTransient->fIsNestedGuest);
5863
5864 /*
5865 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5866 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5867 */
5868 switch (pVCpu->hm.s.enmShadowMode)
5869 {
5870 case PGMMODE_REAL: /* Real-mode. */
5871 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5872 case PGMMODE_32_BIT: /* 32-bit paging. */
5873 {
5874 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5875 break;
5876 }
5877
5878 case PGMMODE_PAE: /* PAE paging. */
5879 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5880 {
5881 u64GuestCr4 |= X86_CR4_PAE;
5882 break;
5883 }
5884
5885 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5886 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5887 {
5888#ifdef VBOX_WITH_64_BITS_GUESTS
5889 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5890 Assert(u64GuestCr4 & X86_CR4_PAE);
5891 break;
5892#endif
5893 }
5894 default:
5895 AssertFailed();
5896 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5897 }
5898 }
5899
5900 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5901 u64GuestCr4 |= fSetCr4;
5902 u64GuestCr4 &= fZapCr4;
5903
5904 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5905 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5906 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5907
5908 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5909 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5910
5911 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5912
5913 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5914 }
5915 return rc;
5916}
5917
5918
5919/**
5920 * Exports the guest debug registers into the guest-state area in the VMCS.
5921 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5922 *
5923 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5924 *
5925 * @returns VBox status code.
5926 * @param pVCpu The cross context virtual CPU structure.
5927 * @param pVmxTransient The VMX-transient structure.
5928 *
5929 * @remarks No-long-jump zone!!!
5930 */
5931static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5932{
5933 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5934
5935 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5936 * stepping. */
5937 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5938 if (pVmxTransient->fIsNestedGuest)
5939 {
5940 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5941 AssertRC(rc);
5942
5943 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5944 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5945 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5946 AssertRC(rc);
5947 return VINF_SUCCESS;
5948 }
5949
5950#ifdef VBOX_STRICT
5951 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5952 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5953 {
5954 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5955 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5956 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5957 }
5958#endif
5959
5960 bool fSteppingDB = false;
5961 bool fInterceptMovDRx = false;
5962 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5963 if (pVCpu->hm.s.fSingleInstruction)
5964 {
5965 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5966 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5967 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5968 {
5969 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5970 Assert(fSteppingDB == false);
5971 }
5972 else
5973 {
5974 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5975 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5976 pVCpu->hm.s.fClearTrapFlag = true;
5977 fSteppingDB = true;
5978 }
5979 }
5980
5981 uint64_t u64GuestDr7;
5982 if ( fSteppingDB
5983 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5984 {
5985 /*
5986 * Use the combined guest and host DRx values found in the hypervisor register set
5987 * because the hypervisor debugger has breakpoints active or someone is single stepping
5988 * on the host side without a monitor trap flag.
5989 *
5990 * Note! DBGF expects a clean DR6 state before executing guest code.
5991 */
5992 if (!CPUMIsHyperDebugStateActive(pVCpu))
5993 {
5994 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5995 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5996 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5997 }
5998
5999 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6000 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6001 pVCpu->hm.s.fUsingHyperDR7 = true;
6002 fInterceptMovDRx = true;
6003 }
6004 else
6005 {
6006 /*
6007 * If the guest has enabled debug registers, we need to load them prior to
6008 * executing guest code so they'll trigger at the right time.
6009 */
6010 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6011 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6012 {
6013 if (!CPUMIsGuestDebugStateActive(pVCpu))
6014 {
6015 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6016 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6017 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6018 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6019 }
6020 Assert(!fInterceptMovDRx);
6021 }
6022 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6023 {
6024 /*
6025 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6026 * must intercept #DB in order to maintain a correct DR6 guest value, and
6027 * because we need to intercept it to prevent nested #DBs from hanging the
6028 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6029 */
6030 fInterceptMovDRx = true;
6031 }
6032
6033 /* Update DR7 with the actual guest value. */
6034 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6035 pVCpu->hm.s.fUsingHyperDR7 = false;
6036 }
6037
6038 if (fInterceptMovDRx)
6039 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6040 else
6041 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6042
6043 /*
6044 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6045 * monitor-trap flag and update our cache.
6046 */
6047 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6048 {
6049 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6050 AssertRC(rc);
6051 pVmcsInfo->u32ProcCtls = uProcCtls;
6052 }
6053
6054 /*
6055 * Update guest DR7.
6056 */
6057 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6058 AssertRC(rc);
6059
6060 /*
6061 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6062 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6063 *
6064 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6065 */
6066 if (fSteppingDB)
6067 {
6068 Assert(pVCpu->hm.s.fSingleInstruction);
6069 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6070
6071 uint32_t fIntrState = 0;
6072 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6073 AssertRC(rc);
6074
6075 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6076 {
6077 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6078 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6079 AssertRC(rc);
6080 }
6081 }
6082
6083 return VINF_SUCCESS;
6084}
6085
6086
6087#ifdef VBOX_STRICT
6088/**
6089 * Strict function to validate segment registers.
6090 *
6091 * @param pVCpu The cross context virtual CPU structure.
6092 * @param pVmcsInfo The VMCS info. object.
6093 *
6094 * @remarks Will import guest CR0 on strict builds during validation of
6095 * segments.
6096 */
6097static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6098{
6099 /*
6100 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6101 *
6102 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6103 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6104 * unusable bit and doesn't change the guest-context value.
6105 */
6106 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6107 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6108 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6109 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6110 && ( !CPUMIsGuestInRealModeEx(pCtx)
6111 && !CPUMIsGuestInV86ModeEx(pCtx)))
6112 {
6113 /* Protected mode checks */
6114 /* CS */
6115 Assert(pCtx->cs.Attr.n.u1Present);
6116 Assert(!(pCtx->cs.Attr.u & 0xf00));
6117 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6118 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6119 || !(pCtx->cs.Attr.n.u1Granularity));
6120 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6121 || (pCtx->cs.Attr.n.u1Granularity));
6122 /* CS cannot be loaded with NULL in protected mode. */
6123 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6124 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6125 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6126 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6127 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6128 else
6129 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6130 /* SS */
6131 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6132 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6133 if ( !(pCtx->cr0 & X86_CR0_PE)
6134 || pCtx->cs.Attr.n.u4Type == 3)
6135 {
6136 Assert(!pCtx->ss.Attr.n.u2Dpl);
6137 }
6138 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6139 {
6140 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6141 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6142 Assert(pCtx->ss.Attr.n.u1Present);
6143 Assert(!(pCtx->ss.Attr.u & 0xf00));
6144 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6145 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6146 || !(pCtx->ss.Attr.n.u1Granularity));
6147 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6148 || (pCtx->ss.Attr.n.u1Granularity));
6149 }
6150 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6151 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6152 {
6153 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6154 Assert(pCtx->ds.Attr.n.u1Present);
6155 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6156 Assert(!(pCtx->ds.Attr.u & 0xf00));
6157 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6158 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6159 || !(pCtx->ds.Attr.n.u1Granularity));
6160 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6161 || (pCtx->ds.Attr.n.u1Granularity));
6162 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6163 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6164 }
6165 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6166 {
6167 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6168 Assert(pCtx->es.Attr.n.u1Present);
6169 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6170 Assert(!(pCtx->es.Attr.u & 0xf00));
6171 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6172 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6173 || !(pCtx->es.Attr.n.u1Granularity));
6174 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6175 || (pCtx->es.Attr.n.u1Granularity));
6176 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6177 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6178 }
6179 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6180 {
6181 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6182 Assert(pCtx->fs.Attr.n.u1Present);
6183 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6184 Assert(!(pCtx->fs.Attr.u & 0xf00));
6185 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6186 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6187 || !(pCtx->fs.Attr.n.u1Granularity));
6188 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6189 || (pCtx->fs.Attr.n.u1Granularity));
6190 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6191 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6192 }
6193 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6194 {
6195 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6196 Assert(pCtx->gs.Attr.n.u1Present);
6197 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6198 Assert(!(pCtx->gs.Attr.u & 0xf00));
6199 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6200 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6201 || !(pCtx->gs.Attr.n.u1Granularity));
6202 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6203 || (pCtx->gs.Attr.n.u1Granularity));
6204 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6205 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6206 }
6207 /* 64-bit capable CPUs. */
6208 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6209 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6210 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6211 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6212 }
6213 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6214 || ( CPUMIsGuestInRealModeEx(pCtx)
6215 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6216 {
6217 /* Real and v86 mode checks. */
6218 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6219 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6220 if (pVmcsInfo->RealMode.fRealOnV86Active)
6221 {
6222 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6223 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6224 }
6225 else
6226 {
6227 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6228 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6229 }
6230
6231 /* CS */
6232 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6233 Assert(pCtx->cs.u32Limit == 0xffff);
6234 Assert(u32CSAttr == 0xf3);
6235 /* SS */
6236 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6237 Assert(pCtx->ss.u32Limit == 0xffff);
6238 Assert(u32SSAttr == 0xf3);
6239 /* DS */
6240 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6241 Assert(pCtx->ds.u32Limit == 0xffff);
6242 Assert(u32DSAttr == 0xf3);
6243 /* ES */
6244 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6245 Assert(pCtx->es.u32Limit == 0xffff);
6246 Assert(u32ESAttr == 0xf3);
6247 /* FS */
6248 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6249 Assert(pCtx->fs.u32Limit == 0xffff);
6250 Assert(u32FSAttr == 0xf3);
6251 /* GS */
6252 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6253 Assert(pCtx->gs.u32Limit == 0xffff);
6254 Assert(u32GSAttr == 0xf3);
6255 /* 64-bit capable CPUs. */
6256 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6257 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6258 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6259 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6260 }
6261}
6262#endif /* VBOX_STRICT */
6263
6264
6265/**
6266 * Exports a guest segment register into the guest-state area in the VMCS.
6267 *
6268 * @returns VBox status code.
6269 * @param pVCpu The cross context virtual CPU structure.
6270 * @param pVmcsInfo The VMCS info. object.
6271 * @param iSegReg The segment register number (X86_SREG_XXX).
6272 * @param pSelReg Pointer to the segment selector.
6273 *
6274 * @remarks No-long-jump zone!!!
6275 */
6276static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6277{
6278 Assert(iSegReg < X86_SREG_COUNT);
6279 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6280 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6281 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6282 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6283
6284 uint32_t u32Access = pSelReg->Attr.u;
6285 if (pVmcsInfo->RealMode.fRealOnV86Active)
6286 {
6287 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6288 u32Access = 0xf3;
6289 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6290 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6291 RT_NOREF_PV(pVCpu);
6292 }
6293 else
6294 {
6295 /*
6296 * The way to differentiate between whether this is really a null selector or was just
6297 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6298 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6299 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6300 * NULL selectors loaded in protected-mode have their attribute as 0.
6301 */
6302 if (!u32Access)
6303 u32Access = X86DESCATTR_UNUSABLE;
6304 }
6305
6306 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6307 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6308 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6309
6310 /*
6311 * Commit it to the VMCS.
6312 */
6313 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6314 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6315 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6316 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6317 return VINF_SUCCESS;
6318}
6319
6320
6321/**
6322 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6323 * area in the VMCS.
6324 *
6325 * @returns VBox status code.
6326 * @param pVCpu The cross context virtual CPU structure.
6327 * @param pVmxTransient The VMX-transient structure.
6328 *
6329 * @remarks Will import guest CR0 on strict builds during validation of
6330 * segments.
6331 * @remarks No-long-jump zone!!!
6332 */
6333static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6334{
6335 int rc = VERR_INTERNAL_ERROR_5;
6336 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6337 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6338 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6339
6340 /*
6341 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6342 */
6343 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6344 {
6345 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6346 {
6347 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6348 if (pVmcsInfo->RealMode.fRealOnV86Active)
6349 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6350 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6351 AssertRC(rc);
6352 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6353 }
6354
6355 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6356 {
6357 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6358 if (pVmcsInfo->RealMode.fRealOnV86Active)
6359 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6360 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6361 AssertRC(rc);
6362 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6363 }
6364
6365 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6366 {
6367 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6368 if (pVmcsInfo->RealMode.fRealOnV86Active)
6369 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6370 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6371 AssertRC(rc);
6372 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6373 }
6374
6375 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6376 {
6377 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6378 if (pVmcsInfo->RealMode.fRealOnV86Active)
6379 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6380 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6381 AssertRC(rc);
6382 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6383 }
6384
6385 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6386 {
6387 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6388 if (pVmcsInfo->RealMode.fRealOnV86Active)
6389 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6390 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6391 AssertRC(rc);
6392 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6393 }
6394
6395 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6396 {
6397 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6398 if (pVmcsInfo->RealMode.fRealOnV86Active)
6399 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6400 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6401 AssertRC(rc);
6402 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6403 }
6404
6405#ifdef VBOX_STRICT
6406 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6407#endif
6408 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6409 pCtx->cs.Attr.u));
6410 }
6411
6412 /*
6413 * Guest TR.
6414 */
6415 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6416 {
6417 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6418
6419 /*
6420 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6421 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6422 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6423 */
6424 uint16_t u16Sel;
6425 uint32_t u32Limit;
6426 uint64_t u64Base;
6427 uint32_t u32AccessRights;
6428 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6429 {
6430 u16Sel = pCtx->tr.Sel;
6431 u32Limit = pCtx->tr.u32Limit;
6432 u64Base = pCtx->tr.u64Base;
6433 u32AccessRights = pCtx->tr.Attr.u;
6434 }
6435 else
6436 {
6437 Assert(!pVmxTransient->fIsNestedGuest);
6438 Assert(pVM->hm.s.vmx.pRealModeTSS);
6439 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6440
6441 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6442 RTGCPHYS GCPhys;
6443 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6444 AssertRCReturn(rc, rc);
6445
6446 X86DESCATTR DescAttr;
6447 DescAttr.u = 0;
6448 DescAttr.n.u1Present = 1;
6449 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6450
6451 u16Sel = 0;
6452 u32Limit = HM_VTX_TSS_SIZE;
6453 u64Base = GCPhys;
6454 u32AccessRights = DescAttr.u;
6455 }
6456
6457 /* Validate. */
6458 Assert(!(u16Sel & RT_BIT(2)));
6459 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6460 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6461 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6462 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6463 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6464 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6465 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6466 Assert( (u32Limit & 0xfff) == 0xfff
6467 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6468 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6469 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6470
6471 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6472 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6473 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6474 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6475
6476 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6477 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6478 }
6479
6480 /*
6481 * Guest GDTR.
6482 */
6483 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6484 {
6485 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6486
6487 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6488 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6489
6490 /* Validate. */
6491 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6492
6493 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6494 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6495 }
6496
6497 /*
6498 * Guest LDTR.
6499 */
6500 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6501 {
6502 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6503
6504 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6505 uint32_t u32Access;
6506 if ( !pVmxTransient->fIsNestedGuest
6507 && !pCtx->ldtr.Attr.u)
6508 u32Access = X86DESCATTR_UNUSABLE;
6509 else
6510 u32Access = pCtx->ldtr.Attr.u;
6511
6512 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6513 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6514 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6515 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6516
6517 /* Validate. */
6518 if (!(u32Access & X86DESCATTR_UNUSABLE))
6519 {
6520 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6521 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6522 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6523 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6524 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6525 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6526 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6527 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6528 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6529 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6530 }
6531
6532 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6533 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6534 }
6535
6536 /*
6537 * Guest IDTR.
6538 */
6539 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6540 {
6541 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6542
6543 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6544 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6545
6546 /* Validate. */
6547 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6548
6549 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6550 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6551 }
6552
6553 return VINF_SUCCESS;
6554}
6555
6556
6557/**
6558 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6559 * areas.
6560 *
6561 * These MSRs will automatically be loaded to the host CPU on every successful
6562 * VM-entry and stored from the host CPU on every successful VM-exit.
6563 *
6564 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6565 * actual host MSR values are not- updated here for performance reasons. See
6566 * hmR0VmxExportHostMsrs().
6567 *
6568 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6569 *
6570 * @returns VBox status code.
6571 * @param pVCpu The cross context virtual CPU structure.
6572 * @param pVmxTransient The VMX-transient structure.
6573 *
6574 * @remarks No-long-jump zone!!!
6575 */
6576static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6577{
6578 AssertPtr(pVCpu);
6579 AssertPtr(pVmxTransient);
6580
6581 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6582 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6583
6584 /*
6585 * MSRs that we use the auto-load/store MSR area in the VMCS.
6586 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6587 * nothing to do here. The host MSR values are updated when it's safe in
6588 * hmR0VmxLazySaveHostMsrs().
6589 *
6590 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6591 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6592 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6593 * for any MSR that are not part of the lazy MSRs so we do not need to place
6594 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6595 */
6596 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6597 {
6598 /* No auto-load/store MSRs currently. */
6599 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6600 }
6601
6602 /*
6603 * Guest Sysenter MSRs.
6604 */
6605 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6606 {
6607 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6608
6609 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6610 {
6611 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6612 AssertRC(rc);
6613 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6614 }
6615
6616 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6617 {
6618 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6619 AssertRC(rc);
6620 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6621 }
6622
6623 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6624 {
6625 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6626 AssertRC(rc);
6627 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6628 }
6629 }
6630
6631 /*
6632 * Guest/host EFER MSR.
6633 */
6634 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6635 {
6636 /* Whether we are using the VMCS to swap the EFER MSR must have been
6637 determined earlier while exporting VM-entry/VM-exit controls. */
6638 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6639 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6640
6641 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6642 {
6643 /*
6644 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6645 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6646 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6647 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6648 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6649 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6650 * during VM-entry.
6651 */
6652 uint64_t uGuestEferMsr = pCtx->msrEFER;
6653 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6654 {
6655 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6656 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6657 else
6658 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6659 }
6660
6661 /*
6662 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6663 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6664 */
6665 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6666 {
6667 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6668 AssertRC(rc);
6669 }
6670 else
6671 {
6672 /*
6673 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6674 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6675 */
6676 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6677 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6678 AssertRCReturn(rc, rc);
6679 }
6680
6681 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6682 }
6683 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6684 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6685
6686 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6687 }
6688
6689 /*
6690 * Other MSRs.
6691 */
6692 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6693 {
6694 /* Speculation Control (R/W). */
6695 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6696 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6697 {
6698 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6699 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6700 AssertRCReturn(rc, rc);
6701 }
6702
6703 /* Last Branch Record. */
6704 if (pVM->hm.s.vmx.fLbr)
6705 {
6706 uint32_t const idFromIpMsrStart = pVM->hm.s.vmx.idLbrFromIpMsrFirst;
6707 uint32_t const idToIpMsrStart = pVM->hm.s.vmx.idLbrToIpMsrFirst;
6708 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
6709 Assert(cLbrStack <= 32);
6710 for (uint32_t i = 0; i < cLbrStack; i++)
6711 {
6712 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6713 pVmxTransient->pVmcsInfo->au64LbrFromIpMsr[i],
6714 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6715 AssertRCReturn(rc, rc);
6716
6717 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6718 if (idToIpMsrStart != 0)
6719 {
6720 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6721 pVmxTransient->pVmcsInfo->au64LbrToIpMsr[i],
6722 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6723 AssertRCReturn(rc, rc);
6724 }
6725 }
6726
6727 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6728 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hm.s.vmx.idLbrTosMsr,
6729 pVmxTransient->pVmcsInfo->u64LbrTosMsr, false /* fSetReadWrite */,
6730 false /* fUpdateHostMsr */);
6731 AssertRCReturn(rc, rc);
6732 }
6733
6734 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6735 }
6736
6737 return VINF_SUCCESS;
6738}
6739
6740
6741/**
6742 * Wrapper for running the guest code in VT-x.
6743 *
6744 * @returns VBox status code, no informational status codes.
6745 * @param pVCpu The cross context virtual CPU structure.
6746 * @param pVmxTransient The VMX-transient structure.
6747 *
6748 * @remarks No-long-jump zone!!!
6749 */
6750DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6751{
6752 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6753 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6754 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6755
6756 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6757
6758 /*
6759 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6760 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6761 * callee-saved and thus the need for this XMM wrapper.
6762 *
6763 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6764 */
6765 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6766 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6767 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6768#ifdef VBOX_WITH_KERNEL_USING_XMM
6769 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6770#else
6771 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6772#endif
6773 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6774 return rc;
6775}
6776
6777
6778/**
6779 * Reports world-switch error and dumps some useful debug info.
6780 *
6781 * @param pVCpu The cross context virtual CPU structure.
6782 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6783 * @param pVmxTransient The VMX-transient structure (only
6784 * exitReason updated).
6785 */
6786static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6787{
6788 Assert(pVCpu);
6789 Assert(pVmxTransient);
6790 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6791
6792 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6793 switch (rcVMRun)
6794 {
6795 case VERR_VMX_INVALID_VMXON_PTR:
6796 AssertFailed();
6797 break;
6798 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6799 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6800 {
6801 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6802 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6803 AssertRC(rc);
6804 hmR0VmxReadExitQualVmcs(pVmxTransient);
6805
6806 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6807 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6808 Cannot do it here as we may have been long preempted. */
6809
6810#ifdef VBOX_STRICT
6811 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6812 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6813 pVmxTransient->uExitReason));
6814 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6815 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6816 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6817 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6818 else
6819 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6820 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6821 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6822
6823 static struct
6824 {
6825 /** Name of the field to log. */
6826 const char *pszName;
6827 /** The VMCS field. */
6828 uint32_t uVmcsField;
6829 /** Whether host support of this field needs to be checked. */
6830 bool fCheckSupport;
6831 } const s_aVmcsFields[] =
6832 {
6833 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6834 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6835 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6836 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6837 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6838 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6839 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6840 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6841 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6842 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6843 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6844 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6845 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6846 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6847 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6848 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6849 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6850 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6851 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6852 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6853 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6854 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6855 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6856 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6857 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6858 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6859 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6860 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6861 /* The order of selector fields below are fixed! */
6862 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6863 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6864 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6865 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6866 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6867 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6868 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6869 /* End of ordered selector fields. */
6870 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6871 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6872 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6873 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6874 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6875 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6876 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6877 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6878 };
6879
6880 RTGDTR HostGdtr;
6881 ASMGetGDTR(&HostGdtr);
6882
6883 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6884 for (uint32_t i = 0; i < cVmcsFields; i++)
6885 {
6886 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6887
6888 bool fSupported;
6889 if (!s_aVmcsFields[i].fCheckSupport)
6890 fSupported = true;
6891 else
6892 {
6893 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6894 switch (uVmcsField)
6895 {
6896 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6897 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6898 case VMX_VMCS32_CTRL_PROC_EXEC2:
6899 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6900 break;
6901 default:
6902 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6903 }
6904 }
6905
6906 if (fSupported)
6907 {
6908 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6909 switch (uWidth)
6910 {
6911 case VMX_VMCSFIELD_WIDTH_16BIT:
6912 {
6913 uint16_t u16Val;
6914 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6915 AssertRC(rc);
6916 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6917
6918 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6919 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6920 {
6921 if (u16Val < HostGdtr.cbGdt)
6922 {
6923 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6924 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6925 "Host FS", "Host GS", "Host TR" };
6926 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6927 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6928 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6929 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6930 }
6931 else
6932 Log4((" Selector value exceeds GDT limit!\n"));
6933 }
6934 break;
6935 }
6936
6937 case VMX_VMCSFIELD_WIDTH_32BIT:
6938 {
6939 uint32_t u32Val;
6940 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6941 AssertRC(rc);
6942 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6943 break;
6944 }
6945
6946 case VMX_VMCSFIELD_WIDTH_64BIT:
6947 case VMX_VMCSFIELD_WIDTH_NATURAL:
6948 {
6949 uint64_t u64Val;
6950 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6951 AssertRC(rc);
6952 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6953 break;
6954 }
6955 }
6956 }
6957 }
6958
6959 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6960 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6961 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6962 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6963 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6964 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6965#endif /* VBOX_STRICT */
6966 break;
6967 }
6968
6969 default:
6970 /* Impossible */
6971 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6972 break;
6973 }
6974}
6975
6976
6977/**
6978 * Sets up the usage of TSC-offsetting and updates the VMCS.
6979 *
6980 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6981 * VMX-preemption timer.
6982 *
6983 * @returns VBox status code.
6984 * @param pVCpu The cross context virtual CPU structure.
6985 * @param pVmxTransient The VMX-transient structure.
6986 *
6987 * @remarks No-long-jump zone!!!
6988 */
6989static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6990{
6991 bool fOffsettedTsc;
6992 bool fParavirtTsc;
6993 uint64_t uTscOffset;
6994 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6995 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6996
6997 if (pVM->hm.s.vmx.fUsePreemptTimer)
6998 {
6999 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7000
7001 /* Make sure the returned values have sane upper and lower boundaries. */
7002 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7003 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7004 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7005 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7006
7007 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7008 * preemption timers here. We probably need to clamp the preemption timer,
7009 * after converting the timer value to the host. */
7010 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7011 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7012 AssertRC(rc);
7013 }
7014 else
7015 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7016
7017 if (fParavirtTsc)
7018 {
7019 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7020 information before every VM-entry, hence disable it for performance sake. */
7021#if 0
7022 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7023 AssertRC(rc);
7024#endif
7025 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7026 }
7027
7028 if ( fOffsettedTsc
7029 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7030 {
7031 if (pVmxTransient->fIsNestedGuest)
7032 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7033 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7034 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7035 }
7036 else
7037 {
7038 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7039 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7040 }
7041}
7042
7043
7044/**
7045 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7046 * VM-exit interruption info type.
7047 *
7048 * @returns The IEM exception flags.
7049 * @param uVector The event vector.
7050 * @param uVmxEventType The VMX event type.
7051 *
7052 * @remarks This function currently only constructs flags required for
7053 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7054 * and CR2 aspects of an exception are not included).
7055 */
7056static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7057{
7058 uint32_t fIemXcptFlags;
7059 switch (uVmxEventType)
7060 {
7061 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7062 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7063 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7064 break;
7065
7066 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7067 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7068 break;
7069
7070 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7071 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7072 break;
7073
7074 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7075 {
7076 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7077 if (uVector == X86_XCPT_BP)
7078 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7079 else if (uVector == X86_XCPT_OF)
7080 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7081 else
7082 {
7083 fIemXcptFlags = 0;
7084 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7085 }
7086 break;
7087 }
7088
7089 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7090 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7091 break;
7092
7093 default:
7094 fIemXcptFlags = 0;
7095 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7096 break;
7097 }
7098 return fIemXcptFlags;
7099}
7100
7101
7102/**
7103 * Sets an event as a pending event to be injected into the guest.
7104 *
7105 * @param pVCpu The cross context virtual CPU structure.
7106 * @param u32IntInfo The VM-entry interruption-information field.
7107 * @param cbInstr The VM-entry instruction length in bytes (for
7108 * software interrupts, exceptions and privileged
7109 * software exceptions).
7110 * @param u32ErrCode The VM-entry exception error code.
7111 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7112 * page-fault.
7113 */
7114DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7115 RTGCUINTPTR GCPtrFaultAddress)
7116{
7117 Assert(!pVCpu->hm.s.Event.fPending);
7118 pVCpu->hm.s.Event.fPending = true;
7119 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7120 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7121 pVCpu->hm.s.Event.cbInstr = cbInstr;
7122 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7123}
7124
7125
7126/**
7127 * Sets an external interrupt as pending-for-injection into the VM.
7128 *
7129 * @param pVCpu The cross context virtual CPU structure.
7130 * @param u8Interrupt The external interrupt vector.
7131 */
7132DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7133{
7134 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7135 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7136 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7137 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7138 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7139}
7140
7141
7142/**
7143 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7144 *
7145 * @param pVCpu The cross context virtual CPU structure.
7146 */
7147DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7148{
7149 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7150 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7151 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7152 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7153 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7154}
7155
7156
7157/**
7158 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7159 *
7160 * @param pVCpu The cross context virtual CPU structure.
7161 */
7162DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7163{
7164 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7165 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7166 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7167 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7168 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7169}
7170
7171
7172/**
7173 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7174 *
7175 * @param pVCpu The cross context virtual CPU structure.
7176 */
7177DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7178{
7179 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7180 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7181 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7182 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7183 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7184}
7185
7186
7187/**
7188 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7189 *
7190 * @param pVCpu The cross context virtual CPU structure.
7191 */
7192DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7193{
7194 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7195 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7196 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7197 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7198 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7199}
7200
7201
7202#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7203/**
7204 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7205 *
7206 * @param pVCpu The cross context virtual CPU structure.
7207 * @param u32ErrCode The error code for the general-protection exception.
7208 */
7209DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7210{
7211 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7212 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7213 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7214 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7215 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7216}
7217
7218
7219/**
7220 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7221 *
7222 * @param pVCpu The cross context virtual CPU structure.
7223 * @param u32ErrCode The error code for the stack exception.
7224 */
7225DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7226{
7227 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7228 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7229 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7230 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7231 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7232}
7233#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7234
7235
7236/**
7237 * Fixes up attributes for the specified segment register.
7238 *
7239 * @param pVCpu The cross context virtual CPU structure.
7240 * @param pSelReg The segment register that needs fixing.
7241 * @param idxSel The VMCS field for the corresponding segment register.
7242 */
7243static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7244{
7245 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7246
7247 /*
7248 * If VT-x marks the segment as unusable, most other bits remain undefined:
7249 * - For CS the L, D and G bits have meaning.
7250 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7251 * - For the remaining data segments no bits are defined.
7252 *
7253 * The present bit and the unusable bit has been observed to be set at the
7254 * same time (the selector was supposed to be invalid as we started executing
7255 * a V8086 interrupt in ring-0).
7256 *
7257 * What should be important for the rest of the VBox code, is that the P bit is
7258 * cleared. Some of the other VBox code recognizes the unusable bit, but
7259 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7260 * safe side here, we'll strip off P and other bits we don't care about. If
7261 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7262 *
7263 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7264 */
7265#ifdef VBOX_STRICT
7266 uint32_t const uAttr = pSelReg->Attr.u;
7267#endif
7268
7269 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7270 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7271 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7272
7273#ifdef VBOX_STRICT
7274 VMMRZCallRing3Disable(pVCpu);
7275 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7276# ifdef DEBUG_bird
7277 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7278 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7279 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7280# endif
7281 VMMRZCallRing3Enable(pVCpu);
7282 NOREF(uAttr);
7283#endif
7284 RT_NOREF2(pVCpu, idxSel);
7285}
7286
7287
7288/**
7289 * Imports a guest segment register from the current VMCS into the guest-CPU
7290 * context.
7291 *
7292 * @param pVCpu The cross context virtual CPU structure.
7293 * @param iSegReg The segment register number (X86_SREG_XXX).
7294 *
7295 * @remarks Called with interrupts and/or preemption disabled.
7296 */
7297static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7298{
7299 Assert(iSegReg < X86_SREG_COUNT);
7300
7301 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7302 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7303 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7304 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7305
7306 uint16_t u16Sel;
7307 uint64_t u64Base;
7308 uint32_t u32Limit, u32Attr;
7309 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7310 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7311 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7312 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7313
7314 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7315 pSelReg->Sel = u16Sel;
7316 pSelReg->ValidSel = u16Sel;
7317 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7318 pSelReg->u32Limit = u32Limit;
7319 pSelReg->u64Base = u64Base;
7320 pSelReg->Attr.u = u32Attr;
7321 if (u32Attr & X86DESCATTR_UNUSABLE)
7322 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7323}
7324
7325
7326/**
7327 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7328 *
7329 * @param pVCpu The cross context virtual CPU structure.
7330 *
7331 * @remarks Called with interrupts and/or preemption disabled.
7332 */
7333static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7334{
7335 uint16_t u16Sel;
7336 uint64_t u64Base;
7337 uint32_t u32Limit, u32Attr;
7338 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7339 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7340 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7341 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7342
7343 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7344 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7345 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7346 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7347 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7348 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7349 if (u32Attr & X86DESCATTR_UNUSABLE)
7350 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7351}
7352
7353
7354/**
7355 * Imports the guest TR from the current VMCS into the guest-CPU context.
7356 *
7357 * @param pVCpu The cross context virtual CPU structure.
7358 *
7359 * @remarks Called with interrupts and/or preemption disabled.
7360 */
7361static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7362{
7363 uint16_t u16Sel;
7364 uint64_t u64Base;
7365 uint32_t u32Limit, u32Attr;
7366 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7367 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7368 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7369 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7370
7371 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7372 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7373 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7374 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7375 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7376 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7377 /* TR is the only selector that can never be unusable. */
7378 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7379}
7380
7381
7382/**
7383 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7384 *
7385 * @param pVCpu The cross context virtual CPU structure.
7386 *
7387 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7388 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7389 * instead!!!
7390 */
7391static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7392{
7393 uint64_t u64Val;
7394 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7395 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7396 {
7397 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7398 AssertRC(rc);
7399
7400 pCtx->rip = u64Val;
7401 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7402 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7403 }
7404}
7405
7406
7407/**
7408 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7409 *
7410 * @param pVCpu The cross context virtual CPU structure.
7411 * @param pVmcsInfo The VMCS info. object.
7412 *
7413 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7414 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7415 * instead!!!
7416 */
7417static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7418{
7419 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7420 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7421 {
7422 uint64_t u64Val;
7423 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7424 AssertRC(rc);
7425
7426 pCtx->rflags.u64 = u64Val;
7427 if (pVmcsInfo->RealMode.fRealOnV86Active)
7428 {
7429 pCtx->eflags.Bits.u1VM = 0;
7430 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7431 }
7432 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7433 }
7434}
7435
7436
7437/**
7438 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7439 * context.
7440 *
7441 * @param pVCpu The cross context virtual CPU structure.
7442 * @param pVmcsInfo The VMCS info. object.
7443 *
7444 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7445 * do not log!
7446 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7447 * instead!!!
7448 */
7449static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7450{
7451 uint32_t u32Val;
7452 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7453 if (!u32Val)
7454 {
7455 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7456 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7457 CPUMSetGuestNmiBlocking(pVCpu, false);
7458 }
7459 else
7460 {
7461 /*
7462 * We must import RIP here to set our EM interrupt-inhibited state.
7463 * We also import RFLAGS as our code that evaluates pending interrupts
7464 * before VM-entry requires it.
7465 */
7466 hmR0VmxImportGuestRip(pVCpu);
7467 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7468
7469 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7470 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7471 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7472 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7473
7474 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7475 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7476 }
7477}
7478
7479
7480/**
7481 * Worker for VMXR0ImportStateOnDemand.
7482 *
7483 * @returns VBox status code.
7484 * @param pVCpu The cross context virtual CPU structure.
7485 * @param pVmcsInfo The VMCS info. object.
7486 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7487 */
7488static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7489{
7490 int rc = VINF_SUCCESS;
7491 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7492 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7493 uint32_t u32Val;
7494
7495 /*
7496 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7497 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7498 * neither are other host platforms.
7499 *
7500 * Committing this temporarily as it prevents BSOD.
7501 *
7502 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7503 */
7504#ifdef RT_OS_WINDOWS
7505 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7506 return VERR_HM_IPE_1;
7507#endif
7508
7509 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7510
7511 /*
7512 * We disable interrupts to make the updating of the state and in particular
7513 * the fExtrn modification atomic wrt to preemption hooks.
7514 */
7515 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7516
7517 fWhat &= pCtx->fExtrn;
7518 if (fWhat)
7519 {
7520 do
7521 {
7522 if (fWhat & CPUMCTX_EXTRN_RIP)
7523 hmR0VmxImportGuestRip(pVCpu);
7524
7525 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7526 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7527
7528 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7529 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7530
7531 if (fWhat & CPUMCTX_EXTRN_RSP)
7532 {
7533 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7534 AssertRC(rc);
7535 }
7536
7537 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7538 {
7539 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7540 if (fWhat & CPUMCTX_EXTRN_CS)
7541 {
7542 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7543 hmR0VmxImportGuestRip(pVCpu);
7544 if (fRealOnV86Active)
7545 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7546 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7547 }
7548 if (fWhat & CPUMCTX_EXTRN_SS)
7549 {
7550 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7551 if (fRealOnV86Active)
7552 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7553 }
7554 if (fWhat & CPUMCTX_EXTRN_DS)
7555 {
7556 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7557 if (fRealOnV86Active)
7558 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7559 }
7560 if (fWhat & CPUMCTX_EXTRN_ES)
7561 {
7562 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7563 if (fRealOnV86Active)
7564 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7565 }
7566 if (fWhat & CPUMCTX_EXTRN_FS)
7567 {
7568 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7569 if (fRealOnV86Active)
7570 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7571 }
7572 if (fWhat & CPUMCTX_EXTRN_GS)
7573 {
7574 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7575 if (fRealOnV86Active)
7576 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7577 }
7578 }
7579
7580 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7581 {
7582 if (fWhat & CPUMCTX_EXTRN_LDTR)
7583 hmR0VmxImportGuestLdtr(pVCpu);
7584
7585 if (fWhat & CPUMCTX_EXTRN_GDTR)
7586 {
7587 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7588 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7589 pCtx->gdtr.cbGdt = u32Val;
7590 }
7591
7592 /* Guest IDTR. */
7593 if (fWhat & CPUMCTX_EXTRN_IDTR)
7594 {
7595 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7596 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7597 pCtx->idtr.cbIdt = u32Val;
7598 }
7599
7600 /* Guest TR. */
7601 if (fWhat & CPUMCTX_EXTRN_TR)
7602 {
7603 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7604 don't need to import that one. */
7605 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7606 hmR0VmxImportGuestTr(pVCpu);
7607 }
7608 }
7609
7610 if (fWhat & CPUMCTX_EXTRN_DR7)
7611 {
7612 if (!pVCpu->hm.s.fUsingHyperDR7)
7613 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7614 }
7615
7616 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7617 {
7618 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7619 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7620 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7621 pCtx->SysEnter.cs = u32Val;
7622 }
7623
7624 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7625 {
7626 if ( pVM->hm.s.fAllow64BitGuests
7627 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7628 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7629 }
7630
7631 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7632 {
7633 if ( pVM->hm.s.fAllow64BitGuests
7634 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7635 {
7636 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7637 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7638 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7639 }
7640 }
7641
7642 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7643 {
7644 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7645 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7646 Assert(pMsrs);
7647 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7648 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7649 for (uint32_t i = 0; i < cMsrs; i++)
7650 {
7651 uint32_t const idMsr = pMsrs[i].u32Msr;
7652 switch (idMsr)
7653 {
7654 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7655 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7656 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7657 default:
7658 {
7659 uint32_t idxLbrMsr;
7660 if (pVM->hm.s.vmx.fLbr)
7661 {
7662 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7663 {
7664 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7665 pVmcsInfo->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7666 break;
7667 }
7668 else if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7669 {
7670 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7671 pVmcsInfo->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7672 break;
7673 }
7674 else if (idMsr == pVM->hm.s.vmx.idLbrTosMsr)
7675 {
7676 pVmcsInfo->u64LbrTosMsr = pMsrs[i].u64Value;
7677 break;
7678 }
7679 /* Fallthru (no break) */
7680 }
7681 pCtx->fExtrn = 0;
7682 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7683 ASMSetFlags(fEFlags);
7684 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7685 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7686 }
7687 }
7688 }
7689 }
7690
7691 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7692 {
7693 if (fWhat & CPUMCTX_EXTRN_CR0)
7694 {
7695 uint64_t u64Cr0;
7696 uint64_t u64Shadow;
7697 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7698 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7699#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7700 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7701 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7702#else
7703 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7704 {
7705 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7706 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7707 }
7708 else
7709 {
7710 /*
7711 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7712 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7713 * re-construct CR0. See @bugref{9180#c95} for details.
7714 */
7715 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7716 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7717 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7718 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7719 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7720 }
7721#endif
7722 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7723 CPUMSetGuestCR0(pVCpu, u64Cr0);
7724 VMMRZCallRing3Enable(pVCpu);
7725 }
7726
7727 if (fWhat & CPUMCTX_EXTRN_CR4)
7728 {
7729 uint64_t u64Cr4;
7730 uint64_t u64Shadow;
7731 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7732 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7733#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7734 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7735 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7736#else
7737 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7738 {
7739 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7740 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7741 }
7742 else
7743 {
7744 /*
7745 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7746 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7747 * re-construct CR4. See @bugref{9180#c95} for details.
7748 */
7749 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7750 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7751 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7752 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7753 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7754 }
7755#endif
7756 pCtx->cr4 = u64Cr4;
7757 }
7758
7759 if (fWhat & CPUMCTX_EXTRN_CR3)
7760 {
7761 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7762 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7763 || ( pVM->hm.s.fNestedPaging
7764 && CPUMIsGuestPagingEnabledEx(pCtx)))
7765 {
7766 uint64_t u64Cr3;
7767 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7768 if (pCtx->cr3 != u64Cr3)
7769 {
7770 pCtx->cr3 = u64Cr3;
7771 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7772 }
7773
7774 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7775 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7776 if (CPUMIsGuestInPAEModeEx(pCtx))
7777 {
7778 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7779 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7780 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7781 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7782 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7783 }
7784 }
7785 }
7786 }
7787
7788#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7789 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7790 {
7791 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7792 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7793 {
7794 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7795 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7796 if (RT_SUCCESS(rc))
7797 { /* likely */ }
7798 else
7799 break;
7800 }
7801 }
7802#endif
7803 } while (0);
7804
7805 if (RT_SUCCESS(rc))
7806 {
7807 /* Update fExtrn. */
7808 pCtx->fExtrn &= ~fWhat;
7809
7810 /* If everything has been imported, clear the HM keeper bit. */
7811 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7812 {
7813 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7814 Assert(!pCtx->fExtrn);
7815 }
7816 }
7817 }
7818 else
7819 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7820
7821 /*
7822 * Restore interrupts.
7823 */
7824 ASMSetFlags(fEFlags);
7825
7826 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7827
7828 if (RT_SUCCESS(rc))
7829 { /* likely */ }
7830 else
7831 return rc;
7832
7833 /*
7834 * Honor any pending CR3 updates.
7835 *
7836 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7837 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7838 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7839 *
7840 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7841 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7842 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7843 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7844 *
7845 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7846 */
7847 if (VMMRZCallRing3IsEnabled(pVCpu))
7848 {
7849 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7850 {
7851 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7852 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7853 }
7854
7855 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7856 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7857
7858 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7859 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7860 }
7861
7862 return VINF_SUCCESS;
7863}
7864
7865
7866/**
7867 * Saves the guest state from the VMCS into the guest-CPU context.
7868 *
7869 * @returns VBox status code.
7870 * @param pVCpu The cross context virtual CPU structure.
7871 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7872 */
7873VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7874{
7875 AssertPtr(pVCpu);
7876 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7877 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7878}
7879
7880
7881/**
7882 * Check per-VM and per-VCPU force flag actions that require us to go back to
7883 * ring-3 for one reason or another.
7884 *
7885 * @returns Strict VBox status code (i.e. informational status codes too)
7886 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7887 * ring-3.
7888 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7889 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7890 * interrupts)
7891 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7892 * all EMTs to be in ring-3.
7893 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7894 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7895 * to the EM loop.
7896 *
7897 * @param pVCpu The cross context virtual CPU structure.
7898 * @param pVmxTransient The VMX-transient structure.
7899 * @param fStepping Whether we are single-stepping the guest using the
7900 * hypervisor debugger.
7901 *
7902 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7903 * is no longer in VMX non-root mode.
7904 */
7905static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
7906{
7907 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7908
7909 /*
7910 * Update pending interrupts into the APIC's IRR.
7911 */
7912 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7913 APICUpdatePendingInterrupts(pVCpu);
7914
7915 /*
7916 * Anything pending? Should be more likely than not if we're doing a good job.
7917 */
7918 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7919 if ( !fStepping
7920 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7921 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7922 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7923 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7924 return VINF_SUCCESS;
7925
7926 /* Pending PGM C3 sync. */
7927 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7928 {
7929 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7930 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7931 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7932 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7933 if (rcStrict != VINF_SUCCESS)
7934 {
7935 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7936 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7937 return rcStrict;
7938 }
7939 }
7940
7941 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7942 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7943 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7944 {
7945 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7946 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7947 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7948 return rc;
7949 }
7950
7951 /* Pending VM request packets, such as hardware interrupts. */
7952 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7953 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7954 {
7955 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7956 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7957 return VINF_EM_PENDING_REQUEST;
7958 }
7959
7960 /* Pending PGM pool flushes. */
7961 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7962 {
7963 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7964 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7965 return VINF_PGM_POOL_FLUSH_PENDING;
7966 }
7967
7968 /* Pending DMA requests. */
7969 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7970 {
7971 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7972 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7973 return VINF_EM_RAW_TO_R3;
7974 }
7975
7976#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7977 /*
7978 * Pending nested-guest events.
7979 *
7980 * Please note the priority of these events are specified and important.
7981 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
7982 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
7983 */
7984 if (pVmxTransient->fIsNestedGuest)
7985 {
7986 /* Pending nested-guest APIC-write. */
7987 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7988 {
7989 Log4Func(("Pending nested-guest APIC-write\n"));
7990 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7991 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7992 return rcStrict;
7993 }
7994
7995 /* Pending nested-guest monitor-trap flag (MTF). */
7996 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
7997 {
7998 Log4Func(("Pending nested-guest MTF\n"));
7999 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8000 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8001 return rcStrict;
8002 }
8003
8004 /* Pending nested-guest VMX-preemption timer expired. */
8005 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8006 {
8007 Log4Func(("Pending nested-guest MTF\n"));
8008 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8009 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8010 return rcStrict;
8011 }
8012 }
8013#else
8014 NOREF(pVmxTransient);
8015#endif
8016
8017 return VINF_SUCCESS;
8018}
8019
8020
8021/**
8022 * Converts any TRPM trap into a pending HM event. This is typically used when
8023 * entering from ring-3 (not longjmp returns).
8024 *
8025 * @param pVCpu The cross context virtual CPU structure.
8026 */
8027static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8028{
8029 Assert(TRPMHasTrap(pVCpu));
8030 Assert(!pVCpu->hm.s.Event.fPending);
8031
8032 uint8_t uVector;
8033 TRPMEVENT enmTrpmEvent;
8034 uint32_t uErrCode;
8035 RTGCUINTPTR GCPtrFaultAddress;
8036 uint8_t cbInstr;
8037 bool fIcebp;
8038
8039 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8040 AssertRC(rc);
8041
8042 uint32_t u32IntInfo;
8043 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8044 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8045
8046 rc = TRPMResetTrap(pVCpu);
8047 AssertRC(rc);
8048 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8049 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8050
8051 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8052}
8053
8054
8055/**
8056 * Converts the pending HM event into a TRPM trap.
8057 *
8058 * @param pVCpu The cross context virtual CPU structure.
8059 */
8060static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8061{
8062 Assert(pVCpu->hm.s.Event.fPending);
8063
8064 /* If a trap was already pending, we did something wrong! */
8065 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8066
8067 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8068 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8069 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8070
8071 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8072
8073 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8074 AssertRC(rc);
8075
8076 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8077 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8078
8079 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8080 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8081 else
8082 {
8083 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8084 switch (uVectorType)
8085 {
8086 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8087 TRPMSetTrapDueToIcebp(pVCpu);
8088 RT_FALL_THRU();
8089 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8090 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8091 {
8092 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8093 || ( uVector == X86_XCPT_BP /* INT3 */
8094 || uVector == X86_XCPT_OF /* INTO */
8095 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8096 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8097 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8098 break;
8099 }
8100 }
8101 }
8102
8103 /* We're now done converting the pending event. */
8104 pVCpu->hm.s.Event.fPending = false;
8105}
8106
8107
8108/**
8109 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8110 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8111 *
8112 * @param pVCpu The cross context virtual CPU structure.
8113 * @param pVmcsInfo The VMCS info. object.
8114 */
8115static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8116{
8117 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8118 {
8119 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8120 {
8121 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8122 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8123 AssertRC(rc);
8124 }
8125 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8126}
8127
8128
8129/**
8130 * Clears the interrupt-window exiting control in the VMCS.
8131 *
8132 * @param pVmcsInfo The VMCS info. object.
8133 */
8134DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8135{
8136 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8137 {
8138 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8139 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8140 AssertRC(rc);
8141 }
8142}
8143
8144
8145/**
8146 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8147 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8148 *
8149 * @param pVCpu The cross context virtual CPU structure.
8150 * @param pVmcsInfo The VMCS info. object.
8151 */
8152static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8153{
8154 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8155 {
8156 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8157 {
8158 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8159 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8160 AssertRC(rc);
8161 Log4Func(("Setup NMI-window exiting\n"));
8162 }
8163 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8164}
8165
8166
8167/**
8168 * Clears the NMI-window exiting control in the VMCS.
8169 *
8170 * @param pVmcsInfo The VMCS info. object.
8171 */
8172DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8173{
8174 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8175 {
8176 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8177 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8178 AssertRC(rc);
8179 }
8180}
8181
8182
8183/**
8184 * Does the necessary state syncing before returning to ring-3 for any reason
8185 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8186 *
8187 * @returns VBox status code.
8188 * @param pVCpu The cross context virtual CPU structure.
8189 * @param fImportState Whether to import the guest state from the VMCS back
8190 * to the guest-CPU context.
8191 *
8192 * @remarks No-long-jmp zone!!!
8193 */
8194static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8195{
8196 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8197 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8198
8199 RTCPUID const idCpu = RTMpCpuId();
8200 Log4Func(("HostCpuId=%u\n", idCpu));
8201
8202 /*
8203 * !!! IMPORTANT !!!
8204 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8205 */
8206
8207 /* Save the guest state if necessary. */
8208 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8209 if (fImportState)
8210 {
8211 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8212 AssertRCReturn(rc, rc);
8213 }
8214
8215 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8216 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8217 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8218
8219 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8220#ifdef VBOX_STRICT
8221 if (CPUMIsHyperDebugStateActive(pVCpu))
8222 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8223#endif
8224 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8225 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8226 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8227
8228 /* Restore host-state bits that VT-x only restores partially. */
8229 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8230 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8231 {
8232 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8233 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8234 }
8235 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8236
8237 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8238 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8239 {
8240 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8241 if (!fImportState)
8242 {
8243 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8244 AssertRCReturn(rc, rc);
8245 }
8246 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8247 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8248 }
8249 else
8250 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8251
8252 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8253 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8254
8255 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8256 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8257 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8258 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8259 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8260 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8261 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8262 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8263 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8264 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8265
8266 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8267
8268 /** @todo This partially defeats the purpose of having preemption hooks.
8269 * The problem is, deregistering the hooks should be moved to a place that
8270 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8271 * context.
8272 */
8273 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8274 AssertRCReturn(rc, rc);
8275
8276#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8277 /*
8278 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8279 * clear a shadow VMCS before allowing that VMCS to become active on another
8280 * logical processor. We may or may not be importing guest state which clears
8281 * it, so cover for it here.
8282 *
8283 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8284 */
8285 if ( pVmcsInfo->pvShadowVmcs
8286 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8287 {
8288 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8289 AssertRCReturn(rc, rc);
8290 }
8291
8292 /*
8293 * Flag that we need to re-export the host state if we switch to this VMCS before
8294 * executing guest or nested-guest code.
8295 */
8296 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8297#endif
8298
8299 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8300 NOREF(idCpu);
8301 return VINF_SUCCESS;
8302}
8303
8304
8305/**
8306 * Leaves the VT-x session.
8307 *
8308 * @returns VBox status code.
8309 * @param pVCpu The cross context virtual CPU structure.
8310 *
8311 * @remarks No-long-jmp zone!!!
8312 */
8313static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8314{
8315 HM_DISABLE_PREEMPT(pVCpu);
8316 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8317 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8318 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8319
8320 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8321 and done this from the VMXR0ThreadCtxCallback(). */
8322 if (!pVCpu->hm.s.fLeaveDone)
8323 {
8324 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8325 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8326 pVCpu->hm.s.fLeaveDone = true;
8327 }
8328 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8329
8330 /*
8331 * !!! IMPORTANT !!!
8332 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8333 */
8334
8335 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8336 /** @todo Deregistering here means we need to VMCLEAR always
8337 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8338 * for calling VMMR0ThreadCtxHookDisable here! */
8339 VMMR0ThreadCtxHookDisable(pVCpu);
8340
8341 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8342 int rc = HMR0LeaveCpu(pVCpu);
8343 HM_RESTORE_PREEMPT();
8344 return rc;
8345}
8346
8347
8348/**
8349 * Does the necessary state syncing before doing a longjmp to ring-3.
8350 *
8351 * @returns VBox status code.
8352 * @param pVCpu The cross context virtual CPU structure.
8353 *
8354 * @remarks No-long-jmp zone!!!
8355 */
8356DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8357{
8358 return hmR0VmxLeaveSession(pVCpu);
8359}
8360
8361
8362/**
8363 * Take necessary actions before going back to ring-3.
8364 *
8365 * An action requires us to go back to ring-3. This function does the necessary
8366 * steps before we can safely return to ring-3. This is not the same as longjmps
8367 * to ring-3, this is voluntary and prepares the guest so it may continue
8368 * executing outside HM (recompiler/IEM).
8369 *
8370 * @returns VBox status code.
8371 * @param pVCpu The cross context virtual CPU structure.
8372 * @param rcExit The reason for exiting to ring-3. Can be
8373 * VINF_VMM_UNKNOWN_RING3_CALL.
8374 */
8375static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8376{
8377 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8378
8379 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8380 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8381 {
8382 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8383 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8384 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8385 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8386 }
8387
8388 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8389 VMMRZCallRing3Disable(pVCpu);
8390 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8391
8392 /*
8393 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8394 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8395 *
8396 * This is because execution may continue from ring-3 and we would need to inject
8397 * the event from there (hence place it back in TRPM).
8398 */
8399 if (pVCpu->hm.s.Event.fPending)
8400 {
8401 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8402 Assert(!pVCpu->hm.s.Event.fPending);
8403
8404 /* Clear the events from the VMCS. */
8405 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8406 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8407 }
8408#ifdef VBOX_STRICT
8409 /*
8410 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8411 * fatal), we don't care about verifying duplicate injection of events. Errors like
8412 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8413 * function so those should and will be checked below.
8414 */
8415 else if (RT_SUCCESS(rcExit))
8416 {
8417 /*
8418 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8419 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8420 * occasionally, see @bugref{9180#c42}.
8421 *
8422 * However, if the VM-entry failed, any VM entry-interruption info. field would
8423 * be left unmodified as the event would not have been injected to the guest. In
8424 * such cases, don't assert, we're not going to continue guest execution anyway.
8425 */
8426 uint32_t uExitReason;
8427 uint32_t uEntryIntInfo;
8428 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8429 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8430 AssertRC(rc);
8431 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8432 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8433 }
8434#endif
8435
8436 /*
8437 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8438 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8439 * (e.g. TPR below threshold).
8440 */
8441 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8442 {
8443 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8444 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8445 }
8446
8447 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8448 and if we're injecting an event we should have a TRPM trap pending. */
8449 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8450#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8451 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8452#endif
8453
8454 /* Save guest state and restore host state bits. */
8455 int rc = hmR0VmxLeaveSession(pVCpu);
8456 AssertRCReturn(rc, rc);
8457 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8458
8459 /* Thread-context hooks are unregistered at this point!!! */
8460 /* Ring-3 callback notifications are unregistered at this point!!! */
8461
8462 /* Sync recompiler state. */
8463 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8464 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8465 | CPUM_CHANGED_LDTR
8466 | CPUM_CHANGED_GDTR
8467 | CPUM_CHANGED_IDTR
8468 | CPUM_CHANGED_TR
8469 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8470 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8471 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8472 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8473
8474 Assert(!pVCpu->hm.s.fClearTrapFlag);
8475
8476 /* Update the exit-to-ring 3 reason. */
8477 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8478
8479 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8480 if ( rcExit != VINF_EM_RAW_INTERRUPT
8481 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8482 {
8483 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8484 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8485 }
8486
8487 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8488 VMMRZCallRing3Enable(pVCpu);
8489 return rc;
8490}
8491
8492
8493/**
8494 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8495 * longjump to ring-3 and possibly get preempted.
8496 *
8497 * @returns VBox status code.
8498 * @param pVCpu The cross context virtual CPU structure.
8499 * @param enmOperation The operation causing the ring-3 longjump.
8500 */
8501VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8502{
8503 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8504 {
8505 /*
8506 * !!! IMPORTANT !!!
8507 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8508 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8509 */
8510 VMMRZCallRing3RemoveNotification(pVCpu);
8511 VMMRZCallRing3Disable(pVCpu);
8512 HM_DISABLE_PREEMPT(pVCpu);
8513
8514 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8515 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8516 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8517 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8518
8519 /* Restore host-state bits that VT-x only restores partially. */
8520 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8521 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8522 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8523 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8524
8525 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8526 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8527 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8528
8529 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8530 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8531 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8532
8533 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8534 cleared as part of importing the guest state above. */
8535 hmR0VmxClearVmcs(pVmcsInfo);
8536
8537 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8538 VMMR0ThreadCtxHookDisable(pVCpu);
8539
8540 /* Leave HM context. This takes care of local init (term). */
8541 HMR0LeaveCpu(pVCpu);
8542 HM_RESTORE_PREEMPT();
8543 return VINF_SUCCESS;
8544 }
8545
8546 Assert(pVCpu);
8547 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8548 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8549
8550 VMMRZCallRing3Disable(pVCpu);
8551 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8552
8553 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8554
8555 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8556 AssertRCReturn(rc, rc);
8557
8558 VMMRZCallRing3Enable(pVCpu);
8559 return VINF_SUCCESS;
8560}
8561
8562
8563/**
8564 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8565 * stack.
8566 *
8567 * @returns Strict VBox status code (i.e. informational status codes too).
8568 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8569 * @param pVCpu The cross context virtual CPU structure.
8570 * @param uValue The value to push to the guest stack.
8571 */
8572static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8573{
8574 /*
8575 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8576 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8577 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8578 */
8579 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8580 if (pCtx->sp == 1)
8581 return VINF_EM_RESET;
8582 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8583 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8584 AssertRC(rc);
8585 return rc;
8586}
8587
8588
8589/**
8590 * Injects an event into the guest upon VM-entry by updating the relevant fields
8591 * in the VM-entry area in the VMCS.
8592 *
8593 * @returns Strict VBox status code (i.e. informational status codes too).
8594 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8595 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8596 *
8597 * @param pVCpu The cross context virtual CPU structure.
8598 * @param pVmxTransient The VMX-transient structure.
8599 * @param pEvent The event being injected.
8600 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8601 * will be updated if necessary. This cannot not be NULL.
8602 * @param fStepping Whether we're single-stepping guest execution and should
8603 * return VINF_EM_DBG_STEPPED if the event is injected
8604 * directly (registers modified by us, not by hardware on
8605 * VM-entry).
8606 */
8607static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8608 uint32_t *pfIntrState)
8609{
8610 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8611 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8612 Assert(pfIntrState);
8613
8614 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8615 uint32_t u32IntInfo = pEvent->u64IntInfo;
8616 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8617 uint32_t const cbInstr = pEvent->cbInstr;
8618 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8619 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8620 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8621
8622#ifdef VBOX_STRICT
8623 /*
8624 * Validate the error-code-valid bit for hardware exceptions.
8625 * No error codes for exceptions in real-mode.
8626 *
8627 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8628 */
8629 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8630 && !CPUMIsGuestInRealModeEx(pCtx))
8631 {
8632 switch (uVector)
8633 {
8634 case X86_XCPT_PF:
8635 case X86_XCPT_DF:
8636 case X86_XCPT_TS:
8637 case X86_XCPT_NP:
8638 case X86_XCPT_SS:
8639 case X86_XCPT_GP:
8640 case X86_XCPT_AC:
8641 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8642 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8643 RT_FALL_THRU();
8644 default:
8645 break;
8646 }
8647 }
8648
8649 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8650 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8651 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8652#endif
8653
8654 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8655 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8656 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8657 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8658 {
8659 Assert(uVector <= X86_XCPT_LAST);
8660 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8661 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8662 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8663 }
8664 else
8665 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8666
8667 /*
8668 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8669 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8670 * interrupt handler in the (real-mode) guest.
8671 *
8672 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8673 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8674 */
8675 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8676 {
8677 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8678 {
8679 /*
8680 * For CPUs with unrestricted guest execution enabled and with the guest
8681 * in real-mode, we must not set the deliver-error-code bit.
8682 *
8683 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8684 */
8685 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8686 }
8687 else
8688 {
8689 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8690 Assert(PDMVmmDevHeapIsEnabled(pVM));
8691 Assert(pVM->hm.s.vmx.pRealModeTSS);
8692 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8693
8694 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8695 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8696 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8697 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8698 AssertRCReturn(rc2, rc2);
8699
8700 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8701 size_t const cbIdtEntry = sizeof(X86IDTR16);
8702 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8703 {
8704 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8705 if (uVector == X86_XCPT_DF)
8706 return VINF_EM_RESET;
8707
8708 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8709 No error codes for exceptions in real-mode. */
8710 if (uVector == X86_XCPT_GP)
8711 {
8712 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8713 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8714 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8715 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8716 HMEVENT EventXcptDf;
8717 RT_ZERO(EventXcptDf);
8718 EventXcptDf.u64IntInfo = uXcptDfInfo;
8719 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8720 }
8721
8722 /*
8723 * If we're injecting an event with no valid IDT entry, inject a #GP.
8724 * No error codes for exceptions in real-mode.
8725 *
8726 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8727 */
8728 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8729 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8730 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8731 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8732 HMEVENT EventXcptGp;
8733 RT_ZERO(EventXcptGp);
8734 EventXcptGp.u64IntInfo = uXcptGpInfo;
8735 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8736 }
8737
8738 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8739 uint16_t uGuestIp = pCtx->ip;
8740 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8741 {
8742 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8743 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8744 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8745 }
8746 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8747 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8748
8749 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8750 X86IDTR16 IdtEntry;
8751 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8752 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8753 AssertRCReturn(rc2, rc2);
8754
8755 /* Construct the stack frame for the interrupt/exception handler. */
8756 VBOXSTRICTRC rcStrict;
8757 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8758 if (rcStrict == VINF_SUCCESS)
8759 {
8760 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8761 if (rcStrict == VINF_SUCCESS)
8762 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8763 }
8764
8765 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8766 if (rcStrict == VINF_SUCCESS)
8767 {
8768 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8769 pCtx->rip = IdtEntry.offSel;
8770 pCtx->cs.Sel = IdtEntry.uSel;
8771 pCtx->cs.ValidSel = IdtEntry.uSel;
8772 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8773 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8774 && uVector == X86_XCPT_PF)
8775 pCtx->cr2 = GCPtrFault;
8776
8777 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8778 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8779 | HM_CHANGED_GUEST_RSP);
8780
8781 /*
8782 * If we delivered a hardware exception (other than an NMI) and if there was
8783 * block-by-STI in effect, we should clear it.
8784 */
8785 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8786 {
8787 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8788 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8789 Log4Func(("Clearing inhibition due to STI\n"));
8790 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8791 }
8792
8793 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8794 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8795
8796 /*
8797 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8798 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8799 */
8800 pVCpu->hm.s.Event.fPending = false;
8801
8802 /*
8803 * If we eventually support nested-guest execution without unrestricted guest execution,
8804 * we should set fInterceptEvents here.
8805 */
8806 Assert(!pVmxTransient->fIsNestedGuest);
8807
8808 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8809 if (fStepping)
8810 rcStrict = VINF_EM_DBG_STEPPED;
8811 }
8812 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8813 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8814 return rcStrict;
8815 }
8816 }
8817
8818 /*
8819 * Validate.
8820 */
8821 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8822 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8823
8824 /*
8825 * Inject the event into the VMCS.
8826 */
8827 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8828 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8829 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8830 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8831 AssertRC(rc);
8832
8833 /*
8834 * Update guest CR2 if this is a page-fault.
8835 */
8836 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8837 pCtx->cr2 = GCPtrFault;
8838
8839 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8840 return VINF_SUCCESS;
8841}
8842
8843
8844/**
8845 * Evaluates the event to be delivered to the guest and sets it as the pending
8846 * event.
8847 *
8848 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8849 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8850 * NOT restore these force-flags.
8851 *
8852 * @returns Strict VBox status code (i.e. informational status codes too).
8853 * @param pVCpu The cross context virtual CPU structure.
8854 * @param pVmxTransient The VMX-transient structure.
8855 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8856 */
8857static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8858{
8859 Assert(pfIntrState);
8860 Assert(!TRPMHasTrap(pVCpu));
8861
8862 /*
8863 * Compute/update guest-interruptibility state related FFs.
8864 * The FFs will be used below while evaluating events to be injected.
8865 */
8866 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8867
8868 /*
8869 * Evaluate if a new event needs to be injected.
8870 * An event that's already pending has already performed all necessary checks.
8871 */
8872 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8873 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8874 if ( !pVCpu->hm.s.Event.fPending
8875 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8876 {
8877 /** @todo SMI. SMIs take priority over NMIs. */
8878
8879 /*
8880 * NMIs.
8881 * NMIs take priority over external interrupts.
8882 */
8883 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8884 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8885 {
8886 /*
8887 * For a guest, the FF always indicates the guest's ability to receive an NMI.
8888 *
8889 * For a nested-guest, the FF always indicates the outer guest's ability to
8890 * receive an NMI while the guest-interruptibility state bit depends on whether
8891 * the nested-hypervisor is using virtual-NMIs.
8892 */
8893 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
8894 {
8895#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8896 if ( fIsNestedGuest
8897 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
8898 return IEMExecVmxVmexitXcptNmi(pVCpu);
8899#endif
8900 hmR0VmxSetPendingXcptNmi(pVCpu);
8901 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8902 Log4Func(("NMI pending injection\n"));
8903
8904 /* We've injected the NMI, bail. */
8905 return VINF_SUCCESS;
8906 }
8907 else if (!fIsNestedGuest)
8908 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8909 }
8910
8911 /*
8912 * External interrupts (PIC/APIC).
8913 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
8914 * We cannot re-request the interrupt from the controller again.
8915 */
8916 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8917 && !pVCpu->hm.s.fSingleInstruction)
8918 {
8919 Assert(!DBGFIsStepping(pVCpu));
8920 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8921 AssertRC(rc);
8922
8923 if (pCtx->eflags.u32 & X86_EFL_IF)
8924 {
8925#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8926 if ( fIsNestedGuest
8927 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8928 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8929 {
8930 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8931 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8932 return rcStrict;
8933 }
8934#endif
8935 uint8_t u8Interrupt;
8936 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8937 if (RT_SUCCESS(rc))
8938 {
8939#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8940 if ( fIsNestedGuest
8941 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8942 && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8943 {
8944 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8945 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8946 return rcStrict;
8947 }
8948#endif
8949 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8950 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
8951 }
8952 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8953 {
8954 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8955
8956 if ( !fIsNestedGuest
8957 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8958 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8959 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8960
8961 /*
8962 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8963 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8964 * need to re-set this force-flag here.
8965 */
8966 }
8967 else
8968 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8969
8970 /* We've injected the interrupt or taken necessary action, bail. */
8971 return VINF_SUCCESS;
8972 }
8973 else if (!fIsNestedGuest)
8974 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8975 }
8976 }
8977 else if (!fIsNestedGuest)
8978 {
8979 /*
8980 * An event is being injected or we are in an interrupt shadow. Check if another event is
8981 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
8982 * the pending event.
8983 */
8984 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8985 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8986 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8987 && !pVCpu->hm.s.fSingleInstruction)
8988 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8989 }
8990 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
8991
8992 return VINF_SUCCESS;
8993}
8994
8995
8996/**
8997 * Injects any pending events into the guest if the guest is in a state to
8998 * receive them.
8999 *
9000 * @returns Strict VBox status code (i.e. informational status codes too).
9001 * @param pVCpu The cross context virtual CPU structure.
9002 * @param pVmxTransient The VMX-transient structure.
9003 * @param fIntrState The VT-x guest-interruptibility state.
9004 * @param fStepping Whether we are single-stepping the guest using the
9005 * hypervisor debugger and should return
9006 * VINF_EM_DBG_STEPPED if the event was dispatched
9007 * directly.
9008 */
9009static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9010{
9011 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9012 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9013
9014#ifdef VBOX_STRICT
9015 /*
9016 * Verify guest-interruptibility state.
9017 *
9018 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9019 * since injecting an event may modify the interruptibility state and we must thus always
9020 * use fIntrState.
9021 */
9022 {
9023 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9024 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9025 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9026 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9027 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9028 Assert(!TRPMHasTrap(pVCpu));
9029 NOREF(fBlockMovSS); NOREF(fBlockSti);
9030 }
9031#endif
9032
9033 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9034 if (pVCpu->hm.s.Event.fPending)
9035 {
9036 /*
9037 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9038 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9039 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9040 *
9041 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9042 */
9043 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9044#ifdef VBOX_STRICT
9045 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9046 {
9047 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9048 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9049 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9050 }
9051 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9052 {
9053 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9054 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9055 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9056 }
9057#endif
9058 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9059 uIntType));
9060
9061 /*
9062 * Inject the event and get any changes to the guest-interruptibility state.
9063 *
9064 * The guest-interruptibility state may need to be updated if we inject the event
9065 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9066 */
9067 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9068 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9069
9070 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9071 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9072 else
9073 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9074 }
9075
9076 /*
9077 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9078 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9079 */
9080 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9081 && !pVmxTransient->fIsNestedGuest)
9082 {
9083 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9084
9085 if (!pVCpu->hm.s.fSingleInstruction)
9086 {
9087 /*
9088 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9089 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9090 */
9091 Assert(!DBGFIsStepping(pVCpu));
9092 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9093 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9094 AssertRC(rc);
9095 }
9096 else
9097 {
9098 /*
9099 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9100 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9101 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9102 * we use MTF, so just make sure it's called before executing guest-code.
9103 */
9104 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9105 }
9106 }
9107 /* else: for nested-guest currently handling while merging controls. */
9108
9109 /*
9110 * Finally, update the guest-interruptibility state.
9111 *
9112 * This is required for the real-on-v86 software interrupt injection, for
9113 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9114 */
9115 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9116 AssertRC(rc);
9117
9118 /*
9119 * There's no need to clear the VM-entry interruption-information field here if we're not
9120 * injecting anything. VT-x clears the valid bit on every VM-exit.
9121 *
9122 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9123 */
9124
9125 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9126 return rcStrict;
9127}
9128
9129
9130/**
9131 * Enters the VT-x session.
9132 *
9133 * @returns VBox status code.
9134 * @param pVCpu The cross context virtual CPU structure.
9135 */
9136VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9137{
9138 AssertPtr(pVCpu);
9139 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9140 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9141
9142 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9143 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9144 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9145
9146#ifdef VBOX_STRICT
9147 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9148 RTCCUINTREG uHostCr4 = ASMGetCR4();
9149 if (!(uHostCr4 & X86_CR4_VMXE))
9150 {
9151 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9152 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9153 }
9154#endif
9155
9156 /*
9157 * Load the appropriate VMCS as the current and active one.
9158 */
9159 PVMXVMCSINFO pVmcsInfo;
9160 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9161 if (!fInNestedGuestMode)
9162 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9163 else
9164 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9165 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9166 if (RT_SUCCESS(rc))
9167 {
9168 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9169 pVCpu->hm.s.fLeaveDone = false;
9170 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9171
9172 /*
9173 * Do the EMT scheduled L1D flush here if needed.
9174 */
9175 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9176 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9177 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9178 hmR0MdsClear();
9179 }
9180 return rc;
9181}
9182
9183
9184/**
9185 * The thread-context callback (only on platforms which support it).
9186 *
9187 * @param enmEvent The thread-context event.
9188 * @param pVCpu The cross context virtual CPU structure.
9189 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9190 * @thread EMT(pVCpu)
9191 */
9192VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9193{
9194 AssertPtr(pVCpu);
9195 RT_NOREF1(fGlobalInit);
9196
9197 switch (enmEvent)
9198 {
9199 case RTTHREADCTXEVENT_OUT:
9200 {
9201 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9202 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9203 VMCPU_ASSERT_EMT(pVCpu);
9204
9205 /* No longjmps (logger flushes, locks) in this fragile context. */
9206 VMMRZCallRing3Disable(pVCpu);
9207 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9208
9209 /* Restore host-state (FPU, debug etc.) */
9210 if (!pVCpu->hm.s.fLeaveDone)
9211 {
9212 /*
9213 * Do -not- import the guest-state here as we might already be in the middle of importing
9214 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9215 */
9216 hmR0VmxLeave(pVCpu, false /* fImportState */);
9217 pVCpu->hm.s.fLeaveDone = true;
9218 }
9219
9220 /* Leave HM context, takes care of local init (term). */
9221 int rc = HMR0LeaveCpu(pVCpu);
9222 AssertRC(rc);
9223
9224 /* Restore longjmp state. */
9225 VMMRZCallRing3Enable(pVCpu);
9226 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9227 break;
9228 }
9229
9230 case RTTHREADCTXEVENT_IN:
9231 {
9232 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9233 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9234 VMCPU_ASSERT_EMT(pVCpu);
9235
9236 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9237 VMMRZCallRing3Disable(pVCpu);
9238 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9239
9240 /* Initialize the bare minimum state required for HM. This takes care of
9241 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9242 int rc = hmR0EnterCpu(pVCpu);
9243 AssertRC(rc);
9244 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9245 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9246
9247 /* Load the active VMCS as the current one. */
9248 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9249 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9250 AssertRC(rc);
9251 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9252 pVCpu->hm.s.fLeaveDone = false;
9253
9254 /* Do the EMT scheduled L1D flush if needed. */
9255 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9256 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9257
9258 /* Restore longjmp state. */
9259 VMMRZCallRing3Enable(pVCpu);
9260 break;
9261 }
9262
9263 default:
9264 break;
9265 }
9266}
9267
9268
9269/**
9270 * Exports the host state into the VMCS host-state area.
9271 * Sets up the VM-exit MSR-load area.
9272 *
9273 * The CPU state will be loaded from these fields on every successful VM-exit.
9274 *
9275 * @returns VBox status code.
9276 * @param pVCpu The cross context virtual CPU structure.
9277 *
9278 * @remarks No-long-jump zone!!!
9279 */
9280static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9281{
9282 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9283
9284 int rc = VINF_SUCCESS;
9285 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9286 {
9287 hmR0VmxExportHostControlRegs();
9288
9289 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9290 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9291
9292 hmR0VmxExportHostMsrs(pVCpu);
9293
9294 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9295 }
9296 return rc;
9297}
9298
9299
9300/**
9301 * Saves the host state in the VMCS host-state.
9302 *
9303 * @returns VBox status code.
9304 * @param pVCpu The cross context virtual CPU structure.
9305 *
9306 * @remarks No-long-jump zone!!!
9307 */
9308VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9309{
9310 AssertPtr(pVCpu);
9311 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9312
9313 /*
9314 * Export the host state here while entering HM context.
9315 * When thread-context hooks are used, we might get preempted and have to re-save the host
9316 * state but most of the time we won't be, so do it here before we disable interrupts.
9317 */
9318 return hmR0VmxExportHostState(pVCpu);
9319}
9320
9321
9322/**
9323 * Exports the guest state into the VMCS guest-state area.
9324 *
9325 * The will typically be done before VM-entry when the guest-CPU state and the
9326 * VMCS state may potentially be out of sync.
9327 *
9328 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9329 * VM-entry controls.
9330 * Sets up the appropriate VMX non-root function to execute guest code based on
9331 * the guest CPU mode.
9332 *
9333 * @returns VBox strict status code.
9334 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9335 * without unrestricted guest execution and the VMMDev is not presently
9336 * mapped (e.g. EFI32).
9337 *
9338 * @param pVCpu The cross context virtual CPU structure.
9339 * @param pVmxTransient The VMX-transient structure.
9340 *
9341 * @remarks No-long-jump zone!!!
9342 */
9343static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9344{
9345 AssertPtr(pVCpu);
9346 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9347 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9348
9349 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9350
9351 /*
9352 * Determine real-on-v86 mode.
9353 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9354 */
9355 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9356 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9357 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9358 pVmcsInfo->RealMode.fRealOnV86Active = false;
9359 else
9360 {
9361 Assert(!pVmxTransient->fIsNestedGuest);
9362 pVmcsInfo->RealMode.fRealOnV86Active = true;
9363 }
9364
9365 /*
9366 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9367 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9368 */
9369 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9370 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9371
9372 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9373 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9374
9375 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9376 if (rcStrict == VINF_SUCCESS)
9377 { /* likely */ }
9378 else
9379 {
9380 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9381 return rcStrict;
9382 }
9383
9384 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9385 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9386
9387 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9388 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9389
9390 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9391 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9392 hmR0VmxExportGuestRip(pVCpu);
9393 hmR0VmxExportGuestRsp(pVCpu);
9394 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9395
9396 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9397 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9398
9399 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9400 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9401 | HM_CHANGED_GUEST_CR2
9402 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9403 | HM_CHANGED_GUEST_X87
9404 | HM_CHANGED_GUEST_SSE_AVX
9405 | HM_CHANGED_GUEST_OTHER_XSAVE
9406 | HM_CHANGED_GUEST_XCRx
9407 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9408 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9409 | HM_CHANGED_GUEST_TSC_AUX
9410 | HM_CHANGED_GUEST_OTHER_MSRS
9411 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9412
9413 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9414 return rc;
9415}
9416
9417
9418/**
9419 * Exports the state shared between the host and guest into the VMCS.
9420 *
9421 * @param pVCpu The cross context virtual CPU structure.
9422 * @param pVmxTransient The VMX-transient structure.
9423 *
9424 * @remarks No-long-jump zone!!!
9425 */
9426static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9427{
9428 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9429 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9430
9431 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9432 {
9433 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9434 AssertRC(rc);
9435 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9436
9437 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9438 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9439 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9440 }
9441
9442 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9443 {
9444 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9445 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9446 }
9447
9448 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9449 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9450}
9451
9452
9453/**
9454 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9455 *
9456 * @returns Strict VBox status code (i.e. informational status codes too).
9457 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9458 * without unrestricted guest execution and the VMMDev is not presently
9459 * mapped (e.g. EFI32).
9460 *
9461 * @param pVCpu The cross context virtual CPU structure.
9462 * @param pVmxTransient The VMX-transient structure.
9463 *
9464 * @remarks No-long-jump zone!!!
9465 */
9466static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9467{
9468 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9469 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9470 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9471
9472#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9473 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9474#endif
9475
9476 /*
9477 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9478 * changes. First try to export only these without going through all other changed-flag checks.
9479 */
9480 VBOXSTRICTRC rcStrict;
9481 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9482 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9483 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9484
9485 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9486 if ( (fCtxChanged & fMinimalMask)
9487 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9488 {
9489 hmR0VmxExportGuestRip(pVCpu);
9490 hmR0VmxExportGuestRsp(pVCpu);
9491 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9492 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9493 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9494 }
9495 /* If anything else also changed, go through the full export routine and export as required. */
9496 else if (fCtxChanged & fCtxMask)
9497 {
9498 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9499 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9500 { /* likely */}
9501 else
9502 {
9503 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9504 VBOXSTRICTRC_VAL(rcStrict)));
9505 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9506 return rcStrict;
9507 }
9508 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9509 }
9510 /* Nothing changed, nothing to load here. */
9511 else
9512 rcStrict = VINF_SUCCESS;
9513
9514#ifdef VBOX_STRICT
9515 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9516 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9517 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9518#endif
9519 return rcStrict;
9520}
9521
9522
9523/**
9524 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9525 * and update error record fields accordingly.
9526 *
9527 * @returns VMX_IGS_* error codes.
9528 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9529 * wrong with the guest state.
9530 *
9531 * @param pVCpu The cross context virtual CPU structure.
9532 * @param pVmcsInfo The VMCS info. object.
9533 *
9534 * @remarks This function assumes our cache of the VMCS controls
9535 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9536 */
9537static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9538{
9539#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9540#define HMVMX_CHECK_BREAK(expr, err) do { \
9541 if (!(expr)) { uError = (err); break; } \
9542 } while (0)
9543
9544 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9545 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9546 uint32_t uError = VMX_IGS_ERROR;
9547 uint32_t u32IntrState = 0;
9548 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9549 do
9550 {
9551 int rc;
9552
9553 /*
9554 * Guest-interruptibility state.
9555 *
9556 * Read this first so that any check that fails prior to those that actually
9557 * require the guest-interruptibility state would still reflect the correct
9558 * VMCS value and avoids causing further confusion.
9559 */
9560 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9561 AssertRC(rc);
9562
9563 uint32_t u32Val;
9564 uint64_t u64Val;
9565
9566 /*
9567 * CR0.
9568 */
9569 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9570 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9571 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9572 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9573 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9574 if (fUnrestrictedGuest)
9575 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9576
9577 uint64_t u64GuestCr0;
9578 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9579 AssertRC(rc);
9580 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9581 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9582 if ( !fUnrestrictedGuest
9583 && (u64GuestCr0 & X86_CR0_PG)
9584 && !(u64GuestCr0 & X86_CR0_PE))
9585 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9586
9587 /*
9588 * CR4.
9589 */
9590 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9591 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9592 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9593
9594 uint64_t u64GuestCr4;
9595 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9596 AssertRC(rc);
9597 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9598 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9599
9600 /*
9601 * IA32_DEBUGCTL MSR.
9602 */
9603 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9604 AssertRC(rc);
9605 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9606 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9607 {
9608 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9609 }
9610 uint64_t u64DebugCtlMsr = u64Val;
9611
9612#ifdef VBOX_STRICT
9613 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9614 AssertRC(rc);
9615 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9616#endif
9617 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9618
9619 /*
9620 * RIP and RFLAGS.
9621 */
9622 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9623 AssertRC(rc);
9624 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9625 if ( !fLongModeGuest
9626 || !pCtx->cs.Attr.n.u1Long)
9627 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9628 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9629 * must be identical if the "IA-32e mode guest" VM-entry
9630 * control is 1 and CS.L is 1. No check applies if the
9631 * CPU supports 64 linear-address bits. */
9632
9633 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9634 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9635 AssertRC(rc);
9636 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9637 VMX_IGS_RFLAGS_RESERVED);
9638 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9639 uint32_t const u32Eflags = u64Val;
9640
9641 if ( fLongModeGuest
9642 || ( fUnrestrictedGuest
9643 && !(u64GuestCr0 & X86_CR0_PE)))
9644 {
9645 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9646 }
9647
9648 uint32_t u32EntryInfo;
9649 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9650 AssertRC(rc);
9651 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9652 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9653
9654 /*
9655 * 64-bit checks.
9656 */
9657 if (fLongModeGuest)
9658 {
9659 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9660 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9661 }
9662
9663 if ( !fLongModeGuest
9664 && (u64GuestCr4 & X86_CR4_PCIDE))
9665 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9666
9667 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9668 * 51:32 beyond the processor's physical-address width are 0. */
9669
9670 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9671 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9672 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9673
9674 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9675 AssertRC(rc);
9676 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9677
9678 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9679 AssertRC(rc);
9680 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9681
9682 /*
9683 * PERF_GLOBAL MSR.
9684 */
9685 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9686 {
9687 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9688 AssertRC(rc);
9689 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9690 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9691 }
9692
9693 /*
9694 * PAT MSR.
9695 */
9696 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9697 {
9698 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9699 AssertRC(rc);
9700 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9701 for (unsigned i = 0; i < 8; i++)
9702 {
9703 uint8_t u8Val = (u64Val & 0xff);
9704 if ( u8Val != 0 /* UC */
9705 && u8Val != 1 /* WC */
9706 && u8Val != 4 /* WT */
9707 && u8Val != 5 /* WP */
9708 && u8Val != 6 /* WB */
9709 && u8Val != 7 /* UC- */)
9710 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9711 u64Val >>= 8;
9712 }
9713 }
9714
9715 /*
9716 * EFER MSR.
9717 */
9718 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9719 {
9720 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9721 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9722 AssertRC(rc);
9723 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9724 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9725 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9726 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9727 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9728 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9729 * iemVmxVmentryCheckGuestState(). */
9730 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9731 || !(u64GuestCr0 & X86_CR0_PG)
9732 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9733 VMX_IGS_EFER_LMA_LME_MISMATCH);
9734 }
9735
9736 /*
9737 * Segment registers.
9738 */
9739 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9740 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9741 if (!(u32Eflags & X86_EFL_VM))
9742 {
9743 /* CS */
9744 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9745 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9746 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9747 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9748 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9749 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9750 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9751 /* CS cannot be loaded with NULL in protected mode. */
9752 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9753 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9754 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9755 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9756 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9757 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9758 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9759 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9760 else
9761 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9762
9763 /* SS */
9764 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9765 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9766 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9767 if ( !(pCtx->cr0 & X86_CR0_PE)
9768 || pCtx->cs.Attr.n.u4Type == 3)
9769 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9770
9771 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9772 {
9773 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9774 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9775 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9776 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9777 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9778 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9779 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9780 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9781 }
9782
9783 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9784 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9785 {
9786 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9787 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9788 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9789 || pCtx->ds.Attr.n.u4Type > 11
9790 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9791 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9792 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9793 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9794 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9795 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9796 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9797 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9798 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9799 }
9800 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9801 {
9802 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9803 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9804 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9805 || pCtx->es.Attr.n.u4Type > 11
9806 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9807 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9808 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9809 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9810 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9811 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9812 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9813 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9814 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9815 }
9816 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9817 {
9818 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9819 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9820 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9821 || pCtx->fs.Attr.n.u4Type > 11
9822 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9823 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9824 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9825 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9826 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9827 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9828 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9829 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9830 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9831 }
9832 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9833 {
9834 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9835 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9836 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9837 || pCtx->gs.Attr.n.u4Type > 11
9838 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9839 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9840 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9841 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9842 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9843 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9844 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9845 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9846 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9847 }
9848 /* 64-bit capable CPUs. */
9849 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9850 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9851 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9852 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9853 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9854 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9855 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9856 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9857 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9858 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9859 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9860 }
9861 else
9862 {
9863 /* V86 mode checks. */
9864 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9865 if (pVmcsInfo->RealMode.fRealOnV86Active)
9866 {
9867 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9868 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9869 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9870 }
9871 else
9872 {
9873 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9874 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9875 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9876 }
9877
9878 /* CS */
9879 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9880 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9881 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9882 /* SS */
9883 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9884 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9885 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9886 /* DS */
9887 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9888 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9889 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9890 /* ES */
9891 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9892 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9893 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9894 /* FS */
9895 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9896 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9897 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9898 /* GS */
9899 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9900 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9901 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9902 /* 64-bit capable CPUs. */
9903 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9904 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9905 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9906 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9907 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9908 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9909 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9910 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9911 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9912 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9913 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9914 }
9915
9916 /*
9917 * TR.
9918 */
9919 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9920 /* 64-bit capable CPUs. */
9921 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9922 if (fLongModeGuest)
9923 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9924 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9925 else
9926 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9927 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9928 VMX_IGS_TR_ATTR_TYPE_INVALID);
9929 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9930 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9931 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9932 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9933 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9934 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9935 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9936 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9937
9938 /*
9939 * GDTR and IDTR (64-bit capable checks).
9940 */
9941 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9942 AssertRC(rc);
9943 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9944
9945 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9946 AssertRC(rc);
9947 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9948
9949 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9950 AssertRC(rc);
9951 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9952
9953 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9954 AssertRC(rc);
9955 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9956
9957 /*
9958 * Guest Non-Register State.
9959 */
9960 /* Activity State. */
9961 uint32_t u32ActivityState;
9962 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9963 AssertRC(rc);
9964 HMVMX_CHECK_BREAK( !u32ActivityState
9965 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9966 VMX_IGS_ACTIVITY_STATE_INVALID);
9967 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9968 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9969
9970 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9971 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9972 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9973
9974 /** @todo Activity state and injecting interrupts. Left as a todo since we
9975 * currently don't use activity states but ACTIVE. */
9976
9977 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9978 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9979
9980 /* Guest interruptibility-state. */
9981 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9982 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9983 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9984 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9985 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9986 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9987 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9988 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9989 {
9990 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9991 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9992 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9993 }
9994 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9995 {
9996 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9997 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9998 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9999 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10000 }
10001 /** @todo Assumes the processor is not in SMM. */
10002 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10003 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10004 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10005 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10006 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10007 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10008 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10009 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10010
10011 /* Pending debug exceptions. */
10012 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10013 AssertRC(rc);
10014 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10015 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10016 u32Val = u64Val; /* For pending debug exceptions checks below. */
10017
10018 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10019 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10020 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10021 {
10022 if ( (u32Eflags & X86_EFL_TF)
10023 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10024 {
10025 /* Bit 14 is PendingDebug.BS. */
10026 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10027 }
10028 if ( !(u32Eflags & X86_EFL_TF)
10029 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10030 {
10031 /* Bit 14 is PendingDebug.BS. */
10032 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10033 }
10034 }
10035
10036 /* VMCS link pointer. */
10037 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10038 AssertRC(rc);
10039 if (u64Val != UINT64_C(0xffffffffffffffff))
10040 {
10041 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10042 /** @todo Bits beyond the processor's physical-address width MBZ. */
10043 /** @todo SMM checks. */
10044 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10045 Assert(pVmcsInfo->pvShadowVmcs);
10046 VMXVMCSREVID VmcsRevId;
10047 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10048 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10049 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10050 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10051 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10052 }
10053
10054 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10055 * not using nested paging? */
10056 if ( pVM->hm.s.fNestedPaging
10057 && !fLongModeGuest
10058 && CPUMIsGuestInPAEModeEx(pCtx))
10059 {
10060 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10061 AssertRC(rc);
10062 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10063
10064 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10065 AssertRC(rc);
10066 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10067
10068 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10069 AssertRC(rc);
10070 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10071
10072 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10073 AssertRC(rc);
10074 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10075 }
10076
10077 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10078 if (uError == VMX_IGS_ERROR)
10079 uError = VMX_IGS_REASON_NOT_FOUND;
10080 } while (0);
10081
10082 pVCpu->hm.s.u32HMError = uError;
10083 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10084 return uError;
10085
10086#undef HMVMX_ERROR_BREAK
10087#undef HMVMX_CHECK_BREAK
10088}
10089
10090
10091/**
10092 * Map the APIC-access page for virtualizing APIC accesses.
10093 *
10094 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10095 * this not done as part of exporting guest state, see @bugref{8721}.
10096 *
10097 * @returns VBox status code.
10098 * @param pVCpu The cross context virtual CPU structure.
10099 */
10100static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10101{
10102 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10103 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10104
10105 Assert(PDMHasApic(pVM));
10106 Assert(u64MsrApicBase);
10107
10108 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10109 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10110
10111 /* Unalias the existing mapping. */
10112 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10113 AssertRCReturn(rc, rc);
10114
10115 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10116 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10117 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10118 AssertRCReturn(rc, rc);
10119
10120 /* Update the per-VCPU cache of the APIC base MSR. */
10121 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10122 return VINF_SUCCESS;
10123}
10124
10125
10126/**
10127 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10128 * CPU.
10129 *
10130 * @param idCpu The ID for the CPU the function is called on.
10131 * @param pvUser1 Null, not used.
10132 * @param pvUser2 Null, not used.
10133 */
10134static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10135{
10136 RT_NOREF3(idCpu, pvUser1, pvUser2);
10137 VMXDispatchHostNmi();
10138}
10139
10140
10141/**
10142 * Dispatching an NMI on the host CPU that received it.
10143 *
10144 * @returns VBox status code.
10145 * @param pVCpu The cross context virtual CPU structure.
10146 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10147 * executing when receiving the host NMI in VMX non-root
10148 * operation.
10149 */
10150static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10151{
10152 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10153 Assert(idCpu != NIL_RTCPUID);
10154
10155 /*
10156 * We don't want to delay dispatching the NMI any more than we have to. However,
10157 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10158 * after executing guest or nested-guest code for the following reasons:
10159 *
10160 * - We would need to perform VMREADs with interrupts disabled and is orders of
10161 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10162 * supported by the host hypervisor.
10163 *
10164 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10165 * longer period of time just for handling an edge case like host NMIs which do
10166 * not occur nearly as frequently as other VM-exits.
10167 *
10168 * Let's cover the most likely scenario first. Check if we are on the target CPU
10169 * and dispatch the NMI right away. This should be much faster than calling into
10170 * RTMpOnSpecific() machinery.
10171 */
10172 bool fDispatched = false;
10173 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10174 if (idCpu == RTMpCpuId())
10175 {
10176 VMXDispatchHostNmi();
10177 fDispatched = true;
10178 }
10179 ASMSetFlags(fEFlags);
10180 if (fDispatched)
10181 {
10182 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10183 return VINF_SUCCESS;
10184 }
10185
10186 /*
10187 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10188 * there should be no race or recursion even if we are unlucky enough to be preempted
10189 * (to the target CPU) without dispatching the host NMI above.
10190 */
10191 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10192 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10193}
10194
10195
10196#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10197/**
10198 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10199 * nested-guest using hardware-assisted VMX.
10200 *
10201 * @param pVCpu The cross context virtual CPU structure.
10202 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10203 * @param pVmcsInfoGst The guest VMCS info. object.
10204 */
10205static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10206{
10207 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10208 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10209 Assert(pu64MsrBitmap);
10210
10211 /*
10212 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10213 * MSR that is intercepted by the guest is also intercepted while executing the
10214 * nested-guest using hardware-assisted VMX.
10215 *
10216 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10217 * nested-guest VM-exit even if the outer guest is not intercepting some
10218 * MSRs. We cannot assume the caller has initialized the nested-guest
10219 * MSR bitmap in this case.
10220 *
10221 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10222 * each of its VM-entry, hence initializing it once per-VM while setting
10223 * up the nested-guest VMCS is not sufficient.
10224 */
10225 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10226 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10227 {
10228 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10229 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10230 Assert(pu64MsrBitmapNstGst);
10231 Assert(pu64MsrBitmapGst);
10232
10233 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10234 for (uint32_t i = 0; i < cFrags; i++)
10235 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10236 }
10237 else
10238 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10239}
10240
10241
10242/**
10243 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10244 * hardware-assisted VMX execution of the nested-guest.
10245 *
10246 * For a guest, we don't modify these controls once we set up the VMCS and hence
10247 * this function is never called.
10248 *
10249 * For nested-guests since the nested hypervisor provides these controls on every
10250 * nested-guest VM-entry and could potentially change them everytime we need to
10251 * merge them before every nested-guest VM-entry.
10252 *
10253 * @returns VBox status code.
10254 * @param pVCpu The cross context virtual CPU structure.
10255 */
10256static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10257{
10258 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10259 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10260 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10261 Assert(pVmcsNstGst);
10262
10263 /*
10264 * Merge the controls with the requirements of the guest VMCS.
10265 *
10266 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10267 * VMCS with the features supported by the physical CPU as it's already done by the
10268 * VMLAUNCH/VMRESUME instruction emulation.
10269 *
10270 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10271 * derived from the VMX features supported by the physical CPU.
10272 */
10273
10274 /* Pin-based VM-execution controls. */
10275 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10276
10277 /* Processor-based VM-execution controls. */
10278 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10279 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10280 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10281 | VMX_PROC_CTLS_USE_TPR_SHADOW
10282 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10283
10284 /* Secondary processor-based VM-execution controls. */
10285 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10286 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10287 | VMX_PROC_CTLS2_INVPCID
10288 | VMX_PROC_CTLS2_VMCS_SHADOWING
10289 | VMX_PROC_CTLS2_RDTSCP
10290 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10291 | VMX_PROC_CTLS2_APIC_REG_VIRT
10292 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10293 | VMX_PROC_CTLS2_VMFUNC));
10294
10295 /*
10296 * VM-entry controls:
10297 * These controls contains state that depends on the nested-guest state (primarily
10298 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10299 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10300 * properly continue executing the nested-guest if the EFER MSR changes but does not
10301 * cause a nested-guest VM-exits.
10302 *
10303 * VM-exit controls:
10304 * These controls specify the host state on return. We cannot use the controls from
10305 * the nested hypervisor state as is as it would contain the guest state rather than
10306 * the host state. Since the host state is subject to change (e.g. preemption, trips
10307 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10308 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10309 *
10310 * VM-entry MSR-load:
10311 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10312 * context by the VMLAUNCH/VMRESUME instruction emulation.
10313 *
10314 * VM-exit MSR-store:
10315 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10316 * back into the VM-exit MSR-store area.
10317 *
10318 * VM-exit MSR-load areas:
10319 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10320 * can entirely ignore what the nested hypervisor wants to load here.
10321 */
10322
10323 /*
10324 * Exception bitmap.
10325 *
10326 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10327 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10328 * code more flexible if intercepting exceptions become more dynamic in the future we do
10329 * it as part of exporting the nested-guest state.
10330 */
10331 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10332
10333 /*
10334 * CR0/CR4 guest/host mask.
10335 *
10336 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10337 * cause VM-exits, so we need to merge them here.
10338 */
10339 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10340 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10341
10342 /*
10343 * Page-fault error-code mask and match.
10344 *
10345 * Although we require unrestricted guest execution (and thereby nested-paging) for
10346 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10347 * normally intercept #PFs, it might intercept them for debugging purposes.
10348 *
10349 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10350 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10351 */
10352 uint32_t u32XcptPFMask;
10353 uint32_t u32XcptPFMatch;
10354 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10355 {
10356 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10357 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10358 }
10359 else
10360 {
10361 u32XcptPFMask = 0;
10362 u32XcptPFMatch = 0;
10363 }
10364
10365 /*
10366 * Pause-Loop exiting.
10367 */
10368 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10369 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10370
10371 /*
10372 * Pending debug exceptions.
10373 * Currently just copy whatever the nested-guest provides us.
10374 */
10375 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10376
10377 /*
10378 * I/O Bitmap.
10379 *
10380 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10381 * intercept all I/O port accesses.
10382 */
10383 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10384 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10385
10386 /*
10387 * VMCS shadowing.
10388 *
10389 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10390 * enabled while executing the nested-guest.
10391 */
10392 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10393
10394 /*
10395 * APIC-access page.
10396 */
10397 RTHCPHYS HCPhysApicAccess;
10398 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10399 {
10400 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10401 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10402
10403 /** @todo NSTVMX: This is not really correct but currently is required to make
10404 * things work. We need to re-enable the page handler when we fallback to
10405 * IEM execution of the nested-guest! */
10406 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10407
10408 void *pvPage;
10409 PGMPAGEMAPLOCK PgLockApicAccess;
10410 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10411 if (RT_SUCCESS(rc))
10412 {
10413 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10414 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10415
10416 /** @todo Handle proper releasing of page-mapping lock later. */
10417 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10418 }
10419 else
10420 return rc;
10421 }
10422 else
10423 HCPhysApicAccess = 0;
10424
10425 /*
10426 * Virtual-APIC page and TPR threshold.
10427 */
10428 RTHCPHYS HCPhysVirtApic;
10429 uint32_t u32TprThreshold;
10430 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10431 {
10432 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10433 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10434
10435 void *pvPage;
10436 PGMPAGEMAPLOCK PgLockVirtApic;
10437 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10438 if (RT_SUCCESS(rc))
10439 {
10440 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10441 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10442
10443 /** @todo Handle proper releasing of page-mapping lock later. */
10444 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10445 }
10446 else
10447 return rc;
10448
10449 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10450 }
10451 else
10452 {
10453 HCPhysVirtApic = 0;
10454 u32TprThreshold = 0;
10455
10456 /*
10457 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10458 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10459 * be taken care of by EPT/shadow paging.
10460 */
10461 if (pVM->hm.s.fAllow64BitGuests)
10462 {
10463 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10464 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10465 }
10466 }
10467
10468 /*
10469 * Validate basic assumptions.
10470 */
10471 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10472 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10473 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10474 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10475
10476 /*
10477 * Commit it to the nested-guest VMCS.
10478 */
10479 int rc = VINF_SUCCESS;
10480 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10481 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10482 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10483 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10484 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10485 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10486 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10487 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10488 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10489 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10490 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10491 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10492 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10493 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10494 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10495 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10496 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10497 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10498 {
10499 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10500 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10501 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10502 }
10503 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10504 {
10505 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10506 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10507 }
10508 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10509 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10510 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10511 AssertRC(rc);
10512
10513 /*
10514 * Update the nested-guest VMCS cache.
10515 */
10516 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10517 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10518 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10519 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10520 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10521 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10522 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10523 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10524 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10525
10526 /*
10527 * We need to flush the TLB if we are switching the APIC-access page address.
10528 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10529 */
10530 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10531 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10532
10533 /*
10534 * MSR bitmap.
10535 *
10536 * The MSR bitmap address has already been initialized while setting up the nested-guest
10537 * VMCS, here we need to merge the MSR bitmaps.
10538 */
10539 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10540 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10541
10542 return VINF_SUCCESS;
10543}
10544#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10545
10546
10547/**
10548 * Does the preparations before executing guest code in VT-x.
10549 *
10550 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10551 * recompiler/IEM. We must be cautious what we do here regarding committing
10552 * guest-state information into the VMCS assuming we assuredly execute the
10553 * guest in VT-x mode.
10554 *
10555 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10556 * the common-state (TRPM/forceflags), we must undo those changes so that the
10557 * recompiler/IEM can (and should) use them when it resumes guest execution.
10558 * Otherwise such operations must be done when we can no longer exit to ring-3.
10559 *
10560 * @returns Strict VBox status code (i.e. informational status codes too).
10561 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10562 * have been disabled.
10563 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10564 * pending events).
10565 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10566 * double-fault into the guest.
10567 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10568 * dispatched directly.
10569 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10570 *
10571 * @param pVCpu The cross context virtual CPU structure.
10572 * @param pVmxTransient The VMX-transient structure.
10573 * @param fStepping Whether we are single-stepping the guest in the
10574 * hypervisor debugger. Makes us ignore some of the reasons
10575 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10576 * if event dispatching took place.
10577 */
10578static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10579{
10580 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10581
10582 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10583
10584#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10585 if (pVmxTransient->fIsNestedGuest)
10586 {
10587 RT_NOREF2(pVCpu, fStepping);
10588 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10589 return VINF_EM_RESCHEDULE_REM;
10590 }
10591#endif
10592
10593#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10594 PGMRZDynMapFlushAutoSet(pVCpu);
10595#endif
10596
10597 /*
10598 * Check and process force flag actions, some of which might require us to go back to ring-3.
10599 */
10600 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10601 if (rcStrict == VINF_SUCCESS)
10602 {
10603 /* FFs don't get set all the time. */
10604#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10605 if ( pVmxTransient->fIsNestedGuest
10606 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10607 {
10608 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10609 return VINF_VMX_VMEXIT;
10610 }
10611#endif
10612 }
10613 else
10614 return rcStrict;
10615
10616 /*
10617 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10618 */
10619 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10620 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10621 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10622 && PDMHasApic(pVM))
10623 {
10624 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10625 AssertRCReturn(rc, rc);
10626 }
10627
10628#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10629 /*
10630 * Merge guest VMCS controls with the nested-guest VMCS controls.
10631 *
10632 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10633 * saved state), we should be okay with merging controls as we initialize the
10634 * guest VMCS controls as part of VM setup phase.
10635 */
10636 if ( pVmxTransient->fIsNestedGuest
10637 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10638 {
10639 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10640 AssertRCReturn(rc, rc);
10641 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10642 }
10643#endif
10644
10645 /*
10646 * Evaluate events to be injected into the guest.
10647 *
10648 * Events in TRPM can be injected without inspecting the guest state.
10649 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10650 * guest to cause a VM-exit the next time they are ready to receive the event.
10651 *
10652 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10653 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10654 * subject to interecption. Otherwise, we should have checked and injected them
10655 * manually elsewhere (IEM).
10656 */
10657 if (TRPMHasTrap(pVCpu))
10658 {
10659 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10660 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10661 }
10662
10663 uint32_t fIntrState;
10664 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10665
10666#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10667 /*
10668 * While evaluating pending events if something failed (unlikely) or if we were
10669 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10670 */
10671 if (rcStrict != VINF_SUCCESS)
10672 return rcStrict;
10673 if ( pVmxTransient->fIsNestedGuest
10674 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10675 {
10676 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10677 return VINF_VMX_VMEXIT;
10678 }
10679#else
10680 Assert(rcStrict == VINF_SUCCESS);
10681#endif
10682
10683 /*
10684 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10685 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10686 * also result in triple-faulting the VM.
10687 *
10688 * With nested-guests, the above does not apply since unrestricted guest execution is a
10689 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10690 */
10691 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10692 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10693 { /* likely */ }
10694 else
10695 {
10696 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10697 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10698 return rcStrict;
10699 }
10700
10701 /*
10702 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10703 * import CR3 themselves. We will need to update them here, as even as late as the above
10704 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10705 * the below force flags to be set.
10706 */
10707 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10708 {
10709 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10710 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10711 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10712 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10713 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10714 }
10715 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10716 {
10717 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10718 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10719 }
10720
10721#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10722 /* Paranoia. */
10723 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10724#endif
10725
10726 /*
10727 * No longjmps to ring-3 from this point on!!!
10728 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10729 * This also disables flushing of the R0-logger instance (if any).
10730 */
10731 VMMRZCallRing3Disable(pVCpu);
10732
10733 /*
10734 * Export the guest state bits.
10735 *
10736 * We cannot perform longjmps while loading the guest state because we do not preserve the
10737 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10738 * CPU migration.
10739 *
10740 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10741 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10742 */
10743 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10744 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10745 { /* likely */ }
10746 else
10747 {
10748 VMMRZCallRing3Enable(pVCpu);
10749 return rcStrict;
10750 }
10751
10752 /*
10753 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10754 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10755 * preemption disabled for a while. Since this is purely to aid the
10756 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10757 * disable interrupt on NT.
10758 *
10759 * We need to check for force-flags that could've possible been altered since we last
10760 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10761 * see @bugref{6398}).
10762 *
10763 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10764 * to ring-3 before executing guest code.
10765 */
10766 pVmxTransient->fEFlags = ASMIntDisableFlags();
10767
10768 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10769 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10770 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10771 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10772 {
10773 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10774 {
10775#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10776 /*
10777 * If we are executing a nested-guest make sure that we should intercept subsequent
10778 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10779 * the VM-exit instruction emulation happy.
10780 */
10781 if (pVmxTransient->fIsNestedGuest)
10782 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10783#endif
10784
10785 /*
10786 * We've injected any pending events. This is really the point of no return (to ring-3).
10787 *
10788 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10789 * returns from this function, so do -not- enable them here.
10790 */
10791 pVCpu->hm.s.Event.fPending = false;
10792 return VINF_SUCCESS;
10793 }
10794
10795 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10796 rcStrict = VINF_EM_RAW_INTERRUPT;
10797 }
10798 else
10799 {
10800 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10801 rcStrict = VINF_EM_RAW_TO_R3;
10802 }
10803
10804 ASMSetFlags(pVmxTransient->fEFlags);
10805 VMMRZCallRing3Enable(pVCpu);
10806
10807 return rcStrict;
10808}
10809
10810
10811/**
10812 * Final preparations before executing guest code using hardware-assisted VMX.
10813 *
10814 * We can no longer get preempted to a different host CPU and there are no returns
10815 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10816 * failures), this function is not intended to fail sans unrecoverable hardware
10817 * errors.
10818 *
10819 * @param pVCpu The cross context virtual CPU structure.
10820 * @param pVmxTransient The VMX-transient structure.
10821 *
10822 * @remarks Called with preemption disabled.
10823 * @remarks No-long-jump zone!!!
10824 */
10825static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10826{
10827 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10828 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10829 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10830 Assert(!pVCpu->hm.s.Event.fPending);
10831
10832 /*
10833 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10834 */
10835 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10836 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10837
10838 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10839 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10840 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10841 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10842
10843 if (!CPUMIsGuestFPUStateActive(pVCpu))
10844 {
10845 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10846 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10847 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10848 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10849 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10850 }
10851
10852 /*
10853 * Re-export the host state bits as we may've been preempted (only happens when
10854 * thread-context hooks are used or when the VM start function changes) or if
10855 * the host CR0 is modified while loading the guest FPU state above.
10856 *
10857 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10858 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10859 * see @bugref{8432}.
10860 *
10861 * This may also happen when switching to/from a nested-guest VMCS without leaving
10862 * ring-0.
10863 */
10864 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10865 {
10866 hmR0VmxExportHostState(pVCpu);
10867 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10868 }
10869 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10870
10871 /*
10872 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10873 */
10874 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10875 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10876 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10877
10878 /*
10879 * Store status of the shared guest/host debug state at the time of VM-entry.
10880 */
10881 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10882 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10883
10884 /*
10885 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10886 * more than one conditional check. The post-run side of our code shall determine
10887 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10888 */
10889 if (pVmcsInfo->pbVirtApic)
10890 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10891
10892 /*
10893 * Update the host MSRs values in the VM-exit MSR-load area.
10894 */
10895 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10896 {
10897 if (pVmcsInfo->cExitMsrLoad > 0)
10898 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10899 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10900 }
10901
10902 /*
10903 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10904 * VMX-preemption timer based on the next virtual sync clock deadline.
10905 */
10906 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10907 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10908 {
10909 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10910 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10911 }
10912
10913 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10914 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10915 if (!fIsRdtscIntercepted)
10916 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10917 else
10918 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10919
10920 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10921 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10922 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10923 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10924 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10925 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10926
10927 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10928
10929 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10930 as we're about to start executing the guest. */
10931
10932 /*
10933 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10934 *
10935 * This is done this late as updating the TSC offsetting/preemption timer above
10936 * figures out if we can skip intercepting RDTSCP by calculating the number of
10937 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10938 */
10939 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10940 && !fIsRdtscIntercepted)
10941 {
10942 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10943
10944 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10945 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10946 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10947 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10948 AssertRC(rc);
10949 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10950 pVmxTransient->fRemoveTscAuxMsr = true;
10951 }
10952
10953#ifdef VBOX_STRICT
10954 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10955 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10956 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10957 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10958#endif
10959
10960#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10961 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10962 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10963 * see @bugref{9180#c54}. */
10964 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10965 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10966 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10967#endif
10968}
10969
10970
10971/**
10972 * First C routine invoked after running guest code using hardware-assisted VMX.
10973 *
10974 * @param pVCpu The cross context virtual CPU structure.
10975 * @param pVmxTransient The VMX-transient structure.
10976 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10977 *
10978 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10979 *
10980 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10981 * unconditionally when it is safe to do so.
10982 */
10983static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10984{
10985 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10986
10987 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10988 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10989 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10990 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10991 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10992 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10993
10994 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10995 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10996 {
10997 uint64_t uGstTsc;
10998 if (!pVmxTransient->fIsNestedGuest)
10999 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11000 else
11001 {
11002 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11003 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11004 }
11005 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11006 }
11007
11008 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11009 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
11010 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11011
11012 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11013 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11014#ifdef VBOX_STRICT
11015 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11016#endif
11017 Assert(!ASMIntAreEnabled());
11018 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11019 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11020
11021#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11022 /*
11023 * Clean all the VMCS fields in the transient structure before reading
11024 * anything from the VMCS.
11025 */
11026 pVmxTransient->uExitReason = 0;
11027 pVmxTransient->uExitIntErrorCode = 0;
11028 pVmxTransient->uExitQual = 0;
11029 pVmxTransient->uGuestLinearAddr = 0;
11030 pVmxTransient->uExitIntInfo = 0;
11031 pVmxTransient->cbExitInstr = 0;
11032 pVmxTransient->ExitInstrInfo.u = 0;
11033 pVmxTransient->uEntryIntInfo = 0;
11034 pVmxTransient->uEntryXcptErrorCode = 0;
11035 pVmxTransient->cbEntryInstr = 0;
11036 pVmxTransient->uIdtVectoringInfo = 0;
11037 pVmxTransient->uIdtVectoringErrorCode = 0;
11038#endif
11039
11040 /*
11041 * Save the basic VM-exit reason and check if the VM-entry failed.
11042 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11043 */
11044 uint32_t uExitReason;
11045 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11046 AssertRC(rc);
11047 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11048 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11049
11050 /*
11051 * Log the VM-exit before logging anything else as otherwise it might be a
11052 * tad confusing what happens before and after the world-switch.
11053 */
11054 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11055
11056 /*
11057 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11058 * bitmap permissions, if it was added before VM-entry.
11059 */
11060 if (pVmxTransient->fRemoveTscAuxMsr)
11061 {
11062 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11063 pVmxTransient->fRemoveTscAuxMsr = false;
11064 }
11065
11066 /*
11067 * Check if VMLAUNCH/VMRESUME succeeded.
11068 * If this failed, we cause a guru meditation and cease further execution.
11069 *
11070 * However, if we are executing a nested-guest we might fail if we use the
11071 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11072 */
11073 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11074 {
11075 /*
11076 * Update the VM-exit history array here even if the VM-entry failed due to:
11077 * - Invalid guest state.
11078 * - MSR loading.
11079 * - Machine-check event.
11080 *
11081 * In any of the above cases we will still have a "valid" VM-exit reason
11082 * despite @a fVMEntryFailed being false.
11083 *
11084 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11085 *
11086 * Note! We don't have CS or RIP at this point. Will probably address that later
11087 * by amending the history entry added here.
11088 */
11089 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11090 UINT64_MAX, uHostTsc);
11091
11092 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11093 {
11094 VMMRZCallRing3Enable(pVCpu);
11095
11096 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11097 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11098
11099#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11100 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11101#endif
11102
11103 /*
11104 * Import the guest-interruptibility state always as we need it while evaluating
11105 * injecting events on re-entry.
11106 *
11107 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11108 * checking for real-mode while exporting the state because all bits that cause
11109 * mode changes wrt CR0 are intercepted.
11110 */
11111 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11112#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11113 | HMVMX_CPUMCTX_EXTRN_ALL
11114#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11115 | CPUMCTX_EXTRN_RFLAGS
11116#endif
11117 ;
11118 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11119 AssertRC(rc);
11120
11121 /*
11122 * Sync the TPR shadow with our APIC state.
11123 */
11124 if ( !pVmxTransient->fIsNestedGuest
11125 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11126 {
11127 Assert(pVmcsInfo->pbVirtApic);
11128 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11129 {
11130 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11131 AssertRC(rc);
11132 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11133 }
11134 }
11135
11136 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11137 return;
11138 }
11139 }
11140#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11141 else if (pVmxTransient->fIsNestedGuest)
11142 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11143#endif
11144 else
11145 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11146
11147 VMMRZCallRing3Enable(pVCpu);
11148}
11149
11150
11151/**
11152 * Runs the guest code using hardware-assisted VMX the normal way.
11153 *
11154 * @returns VBox status code.
11155 * @param pVCpu The cross context virtual CPU structure.
11156 * @param pcLoops Pointer to the number of executed loops.
11157 */
11158static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11159{
11160 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11161 Assert(pcLoops);
11162 Assert(*pcLoops <= cMaxResumeLoops);
11163 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11164
11165#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11166 /*
11167 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11168 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11169 * guest VMCS while entering the VMX ring-0 session.
11170 */
11171 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11172 {
11173 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11174 if (RT_SUCCESS(rc))
11175 { /* likely */ }
11176 else
11177 {
11178 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11179 return rc;
11180 }
11181 }
11182#endif
11183
11184 VMXTRANSIENT VmxTransient;
11185 RT_ZERO(VmxTransient);
11186 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11187
11188 /* Paranoia. */
11189 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11190
11191 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11192 for (;;)
11193 {
11194 Assert(!HMR0SuspendPending());
11195 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11196 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11197
11198 /*
11199 * Preparatory work for running nested-guest code, this may force us to
11200 * return to ring-3.
11201 *
11202 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11203 */
11204 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11205 if (rcStrict != VINF_SUCCESS)
11206 break;
11207
11208 /* Interrupts are disabled at this point! */
11209 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11210 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11211 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11212 /* Interrupts are re-enabled at this point! */
11213
11214 /*
11215 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11216 */
11217 if (RT_SUCCESS(rcRun))
11218 { /* very likely */ }
11219 else
11220 {
11221 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11222 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11223 return rcRun;
11224 }
11225
11226 /*
11227 * Profile the VM-exit.
11228 */
11229 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11230 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11231 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11232 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11233 HMVMX_START_EXIT_DISPATCH_PROF();
11234
11235 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11236
11237 /*
11238 * Handle the VM-exit.
11239 */
11240#ifdef HMVMX_USE_FUNCTION_TABLE
11241 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11242#else
11243 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11244#endif
11245 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11246 if (rcStrict == VINF_SUCCESS)
11247 {
11248 if (++(*pcLoops) <= cMaxResumeLoops)
11249 continue;
11250 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11251 rcStrict = VINF_EM_RAW_INTERRUPT;
11252 }
11253 break;
11254 }
11255
11256 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11257 return rcStrict;
11258}
11259
11260
11261#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11262/**
11263 * Runs the nested-guest code using hardware-assisted VMX.
11264 *
11265 * @returns VBox status code.
11266 * @param pVCpu The cross context virtual CPU structure.
11267 * @param pcLoops Pointer to the number of executed loops.
11268 *
11269 * @sa hmR0VmxRunGuestCodeNormal.
11270 */
11271static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11272{
11273 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11274 Assert(pcLoops);
11275 Assert(*pcLoops <= cMaxResumeLoops);
11276 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11277
11278 /*
11279 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11280 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11281 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11282 */
11283 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11284 {
11285 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11286 if (RT_SUCCESS(rc))
11287 { /* likely */ }
11288 else
11289 {
11290 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11291 return rc;
11292 }
11293 }
11294
11295 VMXTRANSIENT VmxTransient;
11296 RT_ZERO(VmxTransient);
11297 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11298 VmxTransient.fIsNestedGuest = true;
11299
11300 /* Paranoia. */
11301 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11302
11303 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11304 for (;;)
11305 {
11306 Assert(!HMR0SuspendPending());
11307 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11308 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11309
11310 /*
11311 * Preparatory work for running guest code, this may force us to
11312 * return to ring-3.
11313 *
11314 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11315 */
11316 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11317 if (rcStrict != VINF_SUCCESS)
11318 break;
11319
11320 /* Interrupts are disabled at this point! */
11321 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11322 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11323 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11324 /* Interrupts are re-enabled at this point! */
11325
11326 /*
11327 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11328 */
11329 if (RT_SUCCESS(rcRun))
11330 { /* very likely */ }
11331 else
11332 {
11333 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11334 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11335 return rcRun;
11336 }
11337
11338 /*
11339 * Profile the VM-exit.
11340 */
11341 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11342 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11343 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11344 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11345 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11346 HMVMX_START_EXIT_DISPATCH_PROF();
11347
11348 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11349
11350 /*
11351 * Handle the VM-exit.
11352 */
11353 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11354 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11355 if (rcStrict == VINF_SUCCESS)
11356 {
11357 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11358 {
11359 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11360 rcStrict = VINF_VMX_VMEXIT;
11361 }
11362 else
11363 {
11364 if (++(*pcLoops) <= cMaxResumeLoops)
11365 continue;
11366 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11367 rcStrict = VINF_EM_RAW_INTERRUPT;
11368 }
11369 }
11370 else
11371 Assert(rcStrict != VINF_VMX_VMEXIT);
11372 break;
11373 }
11374
11375 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11376 return rcStrict;
11377}
11378#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11379
11380
11381/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11382 * probes.
11383 *
11384 * The following few functions and associated structure contains the bloat
11385 * necessary for providing detailed debug events and dtrace probes as well as
11386 * reliable host side single stepping. This works on the principle of
11387 * "subclassing" the normal execution loop and workers. We replace the loop
11388 * method completely and override selected helpers to add necessary adjustments
11389 * to their core operation.
11390 *
11391 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11392 * any performance for debug and analysis features.
11393 *
11394 * @{
11395 */
11396
11397/**
11398 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11399 * the debug run loop.
11400 */
11401typedef struct VMXRUNDBGSTATE
11402{
11403 /** The RIP we started executing at. This is for detecting that we stepped. */
11404 uint64_t uRipStart;
11405 /** The CS we started executing with. */
11406 uint16_t uCsStart;
11407
11408 /** Whether we've actually modified the 1st execution control field. */
11409 bool fModifiedProcCtls : 1;
11410 /** Whether we've actually modified the 2nd execution control field. */
11411 bool fModifiedProcCtls2 : 1;
11412 /** Whether we've actually modified the exception bitmap. */
11413 bool fModifiedXcptBitmap : 1;
11414
11415 /** We desire the modified the CR0 mask to be cleared. */
11416 bool fClearCr0Mask : 1;
11417 /** We desire the modified the CR4 mask to be cleared. */
11418 bool fClearCr4Mask : 1;
11419 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11420 uint32_t fCpe1Extra;
11421 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11422 uint32_t fCpe1Unwanted;
11423 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11424 uint32_t fCpe2Extra;
11425 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11426 uint32_t bmXcptExtra;
11427 /** The sequence number of the Dtrace provider settings the state was
11428 * configured against. */
11429 uint32_t uDtraceSettingsSeqNo;
11430 /** VM-exits to check (one bit per VM-exit). */
11431 uint32_t bmExitsToCheck[3];
11432
11433 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11434 uint32_t fProcCtlsInitial;
11435 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11436 uint32_t fProcCtls2Initial;
11437 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11438 uint32_t bmXcptInitial;
11439} VMXRUNDBGSTATE;
11440AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11441typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11442
11443
11444/**
11445 * Initializes the VMXRUNDBGSTATE structure.
11446 *
11447 * @param pVCpu The cross context virtual CPU structure of the
11448 * calling EMT.
11449 * @param pVmxTransient The VMX-transient structure.
11450 * @param pDbgState The debug state to initialize.
11451 */
11452static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11453{
11454 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11455 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11456
11457 pDbgState->fModifiedProcCtls = false;
11458 pDbgState->fModifiedProcCtls2 = false;
11459 pDbgState->fModifiedXcptBitmap = false;
11460 pDbgState->fClearCr0Mask = false;
11461 pDbgState->fClearCr4Mask = false;
11462 pDbgState->fCpe1Extra = 0;
11463 pDbgState->fCpe1Unwanted = 0;
11464 pDbgState->fCpe2Extra = 0;
11465 pDbgState->bmXcptExtra = 0;
11466 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11467 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11468 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11469}
11470
11471
11472/**
11473 * Updates the VMSC fields with changes requested by @a pDbgState.
11474 *
11475 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11476 * immediately before executing guest code, i.e. when interrupts are disabled.
11477 * We don't check status codes here as we cannot easily assert or return in the
11478 * latter case.
11479 *
11480 * @param pVCpu The cross context virtual CPU structure.
11481 * @param pVmxTransient The VMX-transient structure.
11482 * @param pDbgState The debug state.
11483 */
11484static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11485{
11486 /*
11487 * Ensure desired flags in VMCS control fields are set.
11488 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11489 *
11490 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11491 * there should be no stale data in pCtx at this point.
11492 */
11493 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11494 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11495 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11496 {
11497 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11498 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11499 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11500 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11501 pDbgState->fModifiedProcCtls = true;
11502 }
11503
11504 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11505 {
11506 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11507 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11508 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11509 pDbgState->fModifiedProcCtls2 = true;
11510 }
11511
11512 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11513 {
11514 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11515 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11516 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11517 pDbgState->fModifiedXcptBitmap = true;
11518 }
11519
11520 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11521 {
11522 pVmcsInfo->u64Cr0Mask = 0;
11523 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11524 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11525 }
11526
11527 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11528 {
11529 pVmcsInfo->u64Cr4Mask = 0;
11530 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11531 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11532 }
11533
11534 NOREF(pVCpu);
11535}
11536
11537
11538/**
11539 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11540 * re-entry next time around.
11541 *
11542 * @returns Strict VBox status code (i.e. informational status codes too).
11543 * @param pVCpu The cross context virtual CPU structure.
11544 * @param pVmxTransient The VMX-transient structure.
11545 * @param pDbgState The debug state.
11546 * @param rcStrict The return code from executing the guest using single
11547 * stepping.
11548 */
11549static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11550 VBOXSTRICTRC rcStrict)
11551{
11552 /*
11553 * Restore VM-exit control settings as we may not reenter this function the
11554 * next time around.
11555 */
11556 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11557
11558 /* We reload the initial value, trigger what we can of recalculations the
11559 next time around. From the looks of things, that's all that's required atm. */
11560 if (pDbgState->fModifiedProcCtls)
11561 {
11562 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11563 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11564 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11565 AssertRC(rc2);
11566 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11567 }
11568
11569 /* We're currently the only ones messing with this one, so just restore the
11570 cached value and reload the field. */
11571 if ( pDbgState->fModifiedProcCtls2
11572 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11573 {
11574 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11575 AssertRC(rc2);
11576 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11577 }
11578
11579 /* If we've modified the exception bitmap, we restore it and trigger
11580 reloading and partial recalculation the next time around. */
11581 if (pDbgState->fModifiedXcptBitmap)
11582 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11583
11584 return rcStrict;
11585}
11586
11587
11588/**
11589 * Configures VM-exit controls for current DBGF and DTrace settings.
11590 *
11591 * This updates @a pDbgState and the VMCS execution control fields to reflect
11592 * the necessary VM-exits demanded by DBGF and DTrace.
11593 *
11594 * @param pVCpu The cross context virtual CPU structure.
11595 * @param pVmxTransient The VMX-transient structure. May update
11596 * fUpdatedTscOffsettingAndPreemptTimer.
11597 * @param pDbgState The debug state.
11598 */
11599static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11600{
11601 /*
11602 * Take down the dtrace serial number so we can spot changes.
11603 */
11604 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11605 ASMCompilerBarrier();
11606
11607 /*
11608 * We'll rebuild most of the middle block of data members (holding the
11609 * current settings) as we go along here, so start by clearing it all.
11610 */
11611 pDbgState->bmXcptExtra = 0;
11612 pDbgState->fCpe1Extra = 0;
11613 pDbgState->fCpe1Unwanted = 0;
11614 pDbgState->fCpe2Extra = 0;
11615 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11616 pDbgState->bmExitsToCheck[i] = 0;
11617
11618 /*
11619 * Software interrupts (INT XXh) - no idea how to trigger these...
11620 */
11621 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11622 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11623 || VBOXVMM_INT_SOFTWARE_ENABLED())
11624 {
11625 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11626 }
11627
11628 /*
11629 * INT3 breakpoints - triggered by #BP exceptions.
11630 */
11631 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11632 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11633
11634 /*
11635 * Exception bitmap and XCPT events+probes.
11636 */
11637 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11638 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11639 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11640
11641 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11642 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11643 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11644 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11645 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11646 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11647 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11648 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11649 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11650 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11651 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11652 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11653 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11654 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11655 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11656 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11657 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11658 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11659
11660 if (pDbgState->bmXcptExtra)
11661 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11662
11663 /*
11664 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11665 *
11666 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11667 * So, when adding/changing/removing please don't forget to update it.
11668 *
11669 * Some of the macros are picking up local variables to save horizontal space,
11670 * (being able to see it in a table is the lesser evil here).
11671 */
11672#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11673 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11674 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11675#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11676 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11677 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11678 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11679 } else do { } while (0)
11680#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11681 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11682 { \
11683 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11684 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11685 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11686 } else do { } while (0)
11687#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11688 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11689 { \
11690 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11691 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11692 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11693 } else do { } while (0)
11694#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11695 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11696 { \
11697 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11698 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11699 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11700 } else do { } while (0)
11701
11702 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11703 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11704 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11705 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11706 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11707
11708 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11709 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11710 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11711 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11712 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11713 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11714 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11715 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11716 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11717 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11718 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11719 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11720 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11721 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11722 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11723 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11724 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11725 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11726 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11727 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11728 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11729 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11730 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11731 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11732 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11733 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11734 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11735 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11736 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11737 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11738 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11739 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11740 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11741 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11742 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11743 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11744
11745 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11746 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11747 {
11748 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11749 | CPUMCTX_EXTRN_APIC_TPR);
11750 AssertRC(rc);
11751
11752#if 0 /** @todo fix me */
11753 pDbgState->fClearCr0Mask = true;
11754 pDbgState->fClearCr4Mask = true;
11755#endif
11756 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11757 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11758 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11759 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11760 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11761 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11762 require clearing here and in the loop if we start using it. */
11763 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11764 }
11765 else
11766 {
11767 if (pDbgState->fClearCr0Mask)
11768 {
11769 pDbgState->fClearCr0Mask = false;
11770 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11771 }
11772 if (pDbgState->fClearCr4Mask)
11773 {
11774 pDbgState->fClearCr4Mask = false;
11775 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11776 }
11777 }
11778 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11779 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11780
11781 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11782 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11783 {
11784 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11785 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11786 }
11787 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11788 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11789
11790 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11791 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11792 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11793 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11794 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11795 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11796 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11797 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11798#if 0 /** @todo too slow, fix handler. */
11799 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11800#endif
11801 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11802
11803 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11804 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11805 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11806 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11807 {
11808 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11809 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11810 }
11811 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11812 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11813 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11814 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11815
11816 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11817 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11818 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11819 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11820 {
11821 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11822 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11823 }
11824 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11825 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11826 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11827 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11828
11829 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11830 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11831 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11832 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11833 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11834 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11835 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11836 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11837 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11838 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11839 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11840 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11841 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11842 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11843 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11844 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11845 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11846 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11847 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11848 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11849 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11850 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11851
11852#undef IS_EITHER_ENABLED
11853#undef SET_ONLY_XBM_IF_EITHER_EN
11854#undef SET_CPE1_XBM_IF_EITHER_EN
11855#undef SET_CPEU_XBM_IF_EITHER_EN
11856#undef SET_CPE2_XBM_IF_EITHER_EN
11857
11858 /*
11859 * Sanitize the control stuff.
11860 */
11861 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11862 if (pDbgState->fCpe2Extra)
11863 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11864 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11865 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11866 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11867 {
11868 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11869 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11870 }
11871
11872 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11873 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11874 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11875 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11876}
11877
11878
11879/**
11880 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11881 * appropriate.
11882 *
11883 * The caller has checked the VM-exit against the
11884 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11885 * already, so we don't have to do that either.
11886 *
11887 * @returns Strict VBox status code (i.e. informational status codes too).
11888 * @param pVCpu The cross context virtual CPU structure.
11889 * @param pVmxTransient The VMX-transient structure.
11890 * @param uExitReason The VM-exit reason.
11891 *
11892 * @remarks The name of this function is displayed by dtrace, so keep it short
11893 * and to the point. No longer than 33 chars long, please.
11894 */
11895static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11896{
11897 /*
11898 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11899 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11900 *
11901 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11902 * does. Must add/change/remove both places. Same ordering, please.
11903 *
11904 * Added/removed events must also be reflected in the next section
11905 * where we dispatch dtrace events.
11906 */
11907 bool fDtrace1 = false;
11908 bool fDtrace2 = false;
11909 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11910 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11911 uint32_t uEventArg = 0;
11912#define SET_EXIT(a_EventSubName) \
11913 do { \
11914 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11915 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11916 } while (0)
11917#define SET_BOTH(a_EventSubName) \
11918 do { \
11919 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11920 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11921 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11922 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11923 } while (0)
11924 switch (uExitReason)
11925 {
11926 case VMX_EXIT_MTF:
11927 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11928
11929 case VMX_EXIT_XCPT_OR_NMI:
11930 {
11931 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11932 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11933 {
11934 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11935 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11936 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11937 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11938 {
11939 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11940 {
11941 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11942 uEventArg = pVmxTransient->uExitIntErrorCode;
11943 }
11944 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11945 switch (enmEvent1)
11946 {
11947 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11948 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11949 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11950 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11951 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11952 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11953 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11954 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11955 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11956 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11957 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11958 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11959 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11960 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11961 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11962 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11963 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11964 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11965 default: break;
11966 }
11967 }
11968 else
11969 AssertFailed();
11970 break;
11971
11972 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11973 uEventArg = idxVector;
11974 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11975 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11976 break;
11977 }
11978 break;
11979 }
11980
11981 case VMX_EXIT_TRIPLE_FAULT:
11982 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11983 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11984 break;
11985 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11986 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11987 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11988 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11989 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11990
11991 /* Instruction specific VM-exits: */
11992 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11993 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11994 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11995 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11996 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11997 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11998 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11999 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12000 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12001 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12002 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12003 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12004 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12005 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12006 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12007 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12008 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12009 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12010 case VMX_EXIT_MOV_CRX:
12011 hmR0VmxReadExitQualVmcs(pVmxTransient);
12012 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12013 SET_BOTH(CRX_READ);
12014 else
12015 SET_BOTH(CRX_WRITE);
12016 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12017 break;
12018 case VMX_EXIT_MOV_DRX:
12019 hmR0VmxReadExitQualVmcs(pVmxTransient);
12020 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12021 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12022 SET_BOTH(DRX_READ);
12023 else
12024 SET_BOTH(DRX_WRITE);
12025 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12026 break;
12027 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12028 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12029 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12030 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12031 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12032 case VMX_EXIT_GDTR_IDTR_ACCESS:
12033 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12034 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12035 {
12036 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12037 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12038 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12039 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12040 }
12041 break;
12042
12043 case VMX_EXIT_LDTR_TR_ACCESS:
12044 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12045 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12046 {
12047 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12048 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12049 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12050 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12051 }
12052 break;
12053
12054 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12055 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12056 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12057 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12058 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12059 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12060 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12061 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12062 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12063 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12064 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12065
12066 /* Events that aren't relevant at this point. */
12067 case VMX_EXIT_EXT_INT:
12068 case VMX_EXIT_INT_WINDOW:
12069 case VMX_EXIT_NMI_WINDOW:
12070 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12071 case VMX_EXIT_PREEMPT_TIMER:
12072 case VMX_EXIT_IO_INSTR:
12073 break;
12074
12075 /* Errors and unexpected events. */
12076 case VMX_EXIT_INIT_SIGNAL:
12077 case VMX_EXIT_SIPI:
12078 case VMX_EXIT_IO_SMI:
12079 case VMX_EXIT_SMI:
12080 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12081 case VMX_EXIT_ERR_MSR_LOAD:
12082 case VMX_EXIT_ERR_MACHINE_CHECK:
12083 case VMX_EXIT_PML_FULL:
12084 case VMX_EXIT_VIRTUALIZED_EOI:
12085 break;
12086
12087 default:
12088 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12089 break;
12090 }
12091#undef SET_BOTH
12092#undef SET_EXIT
12093
12094 /*
12095 * Dtrace tracepoints go first. We do them here at once so we don't
12096 * have to copy the guest state saving and stuff a few dozen times.
12097 * Down side is that we've got to repeat the switch, though this time
12098 * we use enmEvent since the probes are a subset of what DBGF does.
12099 */
12100 if (fDtrace1 || fDtrace2)
12101 {
12102 hmR0VmxReadExitQualVmcs(pVmxTransient);
12103 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12104 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12105 switch (enmEvent1)
12106 {
12107 /** @todo consider which extra parameters would be helpful for each probe. */
12108 case DBGFEVENT_END: break;
12109 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12110 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12111 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12112 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12113 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12114 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12115 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12116 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12117 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12118 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12119 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12120 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12121 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12122 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12123 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12124 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12125 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12126 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12127 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12128 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12129 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12130 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12131 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12132 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12133 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12134 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12135 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12136 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12137 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12138 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12139 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12140 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12141 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12142 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12143 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12144 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12145 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12146 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12147 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12148 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12149 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12150 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12151 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12152 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12153 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12154 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12155 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12156 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12157 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12158 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12159 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12160 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12161 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12162 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12163 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12164 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12165 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12166 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12167 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12168 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12169 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12170 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12171 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12172 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12173 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12174 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12175 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12176 }
12177 switch (enmEvent2)
12178 {
12179 /** @todo consider which extra parameters would be helpful for each probe. */
12180 case DBGFEVENT_END: break;
12181 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12182 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12183 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12184 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12185 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12186 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12187 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12188 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12189 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12190 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12191 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12192 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12193 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12194 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12195 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12196 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12197 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12198 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12199 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12200 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12201 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12202 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12203 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12204 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12205 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12206 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12207 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12208 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12209 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12210 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12211 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12212 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12213 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12214 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12215 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12216 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12217 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12218 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12219 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12220 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12221 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12222 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12223 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12224 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12225 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12226 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12227 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12228 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12229 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12230 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12231 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12232 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12233 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12234 }
12235 }
12236
12237 /*
12238 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12239 * the DBGF call will do a full check).
12240 *
12241 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12242 * Note! If we have to events, we prioritize the first, i.e. the instruction
12243 * one, in order to avoid event nesting.
12244 */
12245 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12246 if ( enmEvent1 != DBGFEVENT_END
12247 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12248 {
12249 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12250 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12251 if (rcStrict != VINF_SUCCESS)
12252 return rcStrict;
12253 }
12254 else if ( enmEvent2 != DBGFEVENT_END
12255 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12256 {
12257 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12258 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12259 if (rcStrict != VINF_SUCCESS)
12260 return rcStrict;
12261 }
12262
12263 return VINF_SUCCESS;
12264}
12265
12266
12267/**
12268 * Single-stepping VM-exit filtering.
12269 *
12270 * This is preprocessing the VM-exits and deciding whether we've gotten far
12271 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12272 * handling is performed.
12273 *
12274 * @returns Strict VBox status code (i.e. informational status codes too).
12275 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12276 * @param pVmxTransient The VMX-transient structure.
12277 * @param pDbgState The debug state.
12278 */
12279DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12280{
12281 /*
12282 * Expensive (saves context) generic dtrace VM-exit probe.
12283 */
12284 uint32_t const uExitReason = pVmxTransient->uExitReason;
12285 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12286 { /* more likely */ }
12287 else
12288 {
12289 hmR0VmxReadExitQualVmcs(pVmxTransient);
12290 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12291 AssertRC(rc);
12292 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12293 }
12294
12295 /*
12296 * Check for host NMI, just to get that out of the way.
12297 */
12298 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12299 { /* normally likely */ }
12300 else
12301 {
12302 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12303 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12304 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12305 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12306 }
12307
12308 /*
12309 * Check for single stepping event if we're stepping.
12310 */
12311 if (pVCpu->hm.s.fSingleInstruction)
12312 {
12313 switch (uExitReason)
12314 {
12315 case VMX_EXIT_MTF:
12316 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12317
12318 /* Various events: */
12319 case VMX_EXIT_XCPT_OR_NMI:
12320 case VMX_EXIT_EXT_INT:
12321 case VMX_EXIT_TRIPLE_FAULT:
12322 case VMX_EXIT_INT_WINDOW:
12323 case VMX_EXIT_NMI_WINDOW:
12324 case VMX_EXIT_TASK_SWITCH:
12325 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12326 case VMX_EXIT_APIC_ACCESS:
12327 case VMX_EXIT_EPT_VIOLATION:
12328 case VMX_EXIT_EPT_MISCONFIG:
12329 case VMX_EXIT_PREEMPT_TIMER:
12330
12331 /* Instruction specific VM-exits: */
12332 case VMX_EXIT_CPUID:
12333 case VMX_EXIT_GETSEC:
12334 case VMX_EXIT_HLT:
12335 case VMX_EXIT_INVD:
12336 case VMX_EXIT_INVLPG:
12337 case VMX_EXIT_RDPMC:
12338 case VMX_EXIT_RDTSC:
12339 case VMX_EXIT_RSM:
12340 case VMX_EXIT_VMCALL:
12341 case VMX_EXIT_VMCLEAR:
12342 case VMX_EXIT_VMLAUNCH:
12343 case VMX_EXIT_VMPTRLD:
12344 case VMX_EXIT_VMPTRST:
12345 case VMX_EXIT_VMREAD:
12346 case VMX_EXIT_VMRESUME:
12347 case VMX_EXIT_VMWRITE:
12348 case VMX_EXIT_VMXOFF:
12349 case VMX_EXIT_VMXON:
12350 case VMX_EXIT_MOV_CRX:
12351 case VMX_EXIT_MOV_DRX:
12352 case VMX_EXIT_IO_INSTR:
12353 case VMX_EXIT_RDMSR:
12354 case VMX_EXIT_WRMSR:
12355 case VMX_EXIT_MWAIT:
12356 case VMX_EXIT_MONITOR:
12357 case VMX_EXIT_PAUSE:
12358 case VMX_EXIT_GDTR_IDTR_ACCESS:
12359 case VMX_EXIT_LDTR_TR_ACCESS:
12360 case VMX_EXIT_INVEPT:
12361 case VMX_EXIT_RDTSCP:
12362 case VMX_EXIT_INVVPID:
12363 case VMX_EXIT_WBINVD:
12364 case VMX_EXIT_XSETBV:
12365 case VMX_EXIT_RDRAND:
12366 case VMX_EXIT_INVPCID:
12367 case VMX_EXIT_VMFUNC:
12368 case VMX_EXIT_RDSEED:
12369 case VMX_EXIT_XSAVES:
12370 case VMX_EXIT_XRSTORS:
12371 {
12372 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12373 AssertRCReturn(rc, rc);
12374 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12375 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12376 return VINF_EM_DBG_STEPPED;
12377 break;
12378 }
12379
12380 /* Errors and unexpected events: */
12381 case VMX_EXIT_INIT_SIGNAL:
12382 case VMX_EXIT_SIPI:
12383 case VMX_EXIT_IO_SMI:
12384 case VMX_EXIT_SMI:
12385 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12386 case VMX_EXIT_ERR_MSR_LOAD:
12387 case VMX_EXIT_ERR_MACHINE_CHECK:
12388 case VMX_EXIT_PML_FULL:
12389 case VMX_EXIT_VIRTUALIZED_EOI:
12390 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12391 break;
12392
12393 default:
12394 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12395 break;
12396 }
12397 }
12398
12399 /*
12400 * Check for debugger event breakpoints and dtrace probes.
12401 */
12402 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12403 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12404 {
12405 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12406 if (rcStrict != VINF_SUCCESS)
12407 return rcStrict;
12408 }
12409
12410 /*
12411 * Normal processing.
12412 */
12413#ifdef HMVMX_USE_FUNCTION_TABLE
12414 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12415#else
12416 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12417#endif
12418}
12419
12420
12421/**
12422 * Single steps guest code using hardware-assisted VMX.
12423 *
12424 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12425 * but single-stepping through the hypervisor debugger.
12426 *
12427 * @returns Strict VBox status code (i.e. informational status codes too).
12428 * @param pVCpu The cross context virtual CPU structure.
12429 * @param pcLoops Pointer to the number of executed loops.
12430 *
12431 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12432 */
12433static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12434{
12435 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12436 Assert(pcLoops);
12437 Assert(*pcLoops <= cMaxResumeLoops);
12438
12439 VMXTRANSIENT VmxTransient;
12440 RT_ZERO(VmxTransient);
12441 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12442
12443 /* Set HMCPU indicators. */
12444 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12445 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12446 pVCpu->hm.s.fDebugWantRdTscExit = false;
12447 pVCpu->hm.s.fUsingDebugLoop = true;
12448
12449 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12450 VMXRUNDBGSTATE DbgState;
12451 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12452 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12453
12454 /*
12455 * The loop.
12456 */
12457 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12458 for (;;)
12459 {
12460 Assert(!HMR0SuspendPending());
12461 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12462 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12463 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12464
12465 /* Set up VM-execution controls the next two can respond to. */
12466 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12467
12468 /*
12469 * Preparatory work for running guest code, this may force us to
12470 * return to ring-3.
12471 *
12472 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12473 */
12474 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12475 if (rcStrict != VINF_SUCCESS)
12476 break;
12477
12478 /* Interrupts are disabled at this point! */
12479 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12480
12481 /* Override any obnoxious code in the above two calls. */
12482 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12483
12484 /*
12485 * Finally execute the guest.
12486 */
12487 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12488
12489 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12490 /* Interrupts are re-enabled at this point! */
12491
12492 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12493 if (RT_SUCCESS(rcRun))
12494 { /* very likely */ }
12495 else
12496 {
12497 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12498 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12499 return rcRun;
12500 }
12501
12502 /* Profile the VM-exit. */
12503 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12504 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12505 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12506 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12507 HMVMX_START_EXIT_DISPATCH_PROF();
12508
12509 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12510
12511 /*
12512 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12513 */
12514 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12515 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12516 if (rcStrict != VINF_SUCCESS)
12517 break;
12518 if (++(*pcLoops) > cMaxResumeLoops)
12519 {
12520 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12521 rcStrict = VINF_EM_RAW_INTERRUPT;
12522 break;
12523 }
12524
12525 /*
12526 * Stepping: Did the RIP change, if so, consider it a single step.
12527 * Otherwise, make sure one of the TFs gets set.
12528 */
12529 if (fStepping)
12530 {
12531 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12532 AssertRC(rc);
12533 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12534 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12535 {
12536 rcStrict = VINF_EM_DBG_STEPPED;
12537 break;
12538 }
12539 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12540 }
12541
12542 /*
12543 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12544 */
12545 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12546 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12547 }
12548
12549 /*
12550 * Clear the X86_EFL_TF if necessary.
12551 */
12552 if (pVCpu->hm.s.fClearTrapFlag)
12553 {
12554 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12555 AssertRC(rc);
12556 pVCpu->hm.s.fClearTrapFlag = false;
12557 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12558 }
12559 /** @todo there seems to be issues with the resume flag when the monitor trap
12560 * flag is pending without being used. Seen early in bios init when
12561 * accessing APIC page in protected mode. */
12562
12563 /*
12564 * Restore VM-exit control settings as we may not re-enter this function the
12565 * next time around.
12566 */
12567 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12568
12569 /* Restore HMCPU indicators. */
12570 pVCpu->hm.s.fUsingDebugLoop = false;
12571 pVCpu->hm.s.fDebugWantRdTscExit = false;
12572 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12573
12574 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12575 return rcStrict;
12576}
12577
12578
12579/** @} */
12580
12581
12582/**
12583 * Checks if any expensive dtrace probes are enabled and we should go to the
12584 * debug loop.
12585 *
12586 * @returns true if we should use debug loop, false if not.
12587 */
12588static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12589{
12590 /* It's probably faster to OR the raw 32-bit counter variables together.
12591 Since the variables are in an array and the probes are next to one
12592 another (more or less), we have good locality. So, better read
12593 eight-nine cache lines ever time and only have one conditional, than
12594 128+ conditionals, right? */
12595 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12596 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12597 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12598 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12599 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12600 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12601 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12602 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12603 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12604 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12605 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12606 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12607 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12608 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12609 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12610 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12611 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12612 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12613 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12614 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12615 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12616 ) != 0
12617 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12618 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12619 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12620 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12621 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12622 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12623 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12624 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12625 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12626 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12627 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12628 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12629 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12630 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12631 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12632 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12633 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12634 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12635 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12636 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12637 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12638 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12639 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12640 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12641 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12642 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12643 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12644 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12645 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12646 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12647 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12648 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12649 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12650 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12651 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12652 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12653 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12654 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12655 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12656 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12657 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12658 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12659 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12660 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12661 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12662 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12663 ) != 0
12664 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12665 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12666 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12667 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12668 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12669 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12670 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12671 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12672 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12673 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12674 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12675 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12676 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12677 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12678 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12679 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12680 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12681 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12682 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12683 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12684 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12685 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12686 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12687 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12688 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12689 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12690 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12691 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12692 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12693 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12694 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12695 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12696 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12697 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12698 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12699 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12700 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12701 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12702 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12703 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12704 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12705 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12706 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12707 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12708 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12709 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12710 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12711 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12712 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12713 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12714 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12715 ) != 0;
12716}
12717
12718
12719/**
12720 * Runs the guest using hardware-assisted VMX.
12721 *
12722 * @returns Strict VBox status code (i.e. informational status codes too).
12723 * @param pVCpu The cross context virtual CPU structure.
12724 */
12725VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12726{
12727 AssertPtr(pVCpu);
12728 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12729 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12730 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12731 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12732
12733 VBOXSTRICTRC rcStrict;
12734 uint32_t cLoops = 0;
12735 for (;;)
12736 {
12737#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12738 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12739#else
12740 NOREF(pCtx);
12741 bool const fInNestedGuestMode = false;
12742#endif
12743 if (!fInNestedGuestMode)
12744 {
12745 if ( !pVCpu->hm.s.fUseDebugLoop
12746 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12747 && !DBGFIsStepping(pVCpu)
12748 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12749 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12750 else
12751 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12752 }
12753#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12754 else
12755 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12756
12757 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12758 {
12759 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12760 continue;
12761 }
12762 if (rcStrict == VINF_VMX_VMEXIT)
12763 {
12764 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12765 continue;
12766 }
12767#endif
12768 break;
12769 }
12770
12771 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12772 switch (rcLoop)
12773 {
12774 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12775 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12776 }
12777
12778 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12779 if (RT_FAILURE(rc2))
12780 {
12781 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12782 rcStrict = rc2;
12783 }
12784 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12785 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12786 return rcStrict;
12787}
12788
12789
12790#ifndef HMVMX_USE_FUNCTION_TABLE
12791/**
12792 * Handles a guest VM-exit from hardware-assisted VMX execution.
12793 *
12794 * @returns Strict VBox status code (i.e. informational status codes too).
12795 * @param pVCpu The cross context virtual CPU structure.
12796 * @param pVmxTransient The VMX-transient structure.
12797 */
12798DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12799{
12800#ifdef DEBUG_ramshankar
12801# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12802 do { \
12803 if (a_fSave != 0) \
12804 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12805 VBOXSTRICTRC rcStrict = a_CallExpr; \
12806 if (a_fSave != 0) \
12807 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12808 return rcStrict; \
12809 } while (0)
12810#else
12811# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12812#endif
12813 uint32_t const uExitReason = pVmxTransient->uExitReason;
12814 switch (uExitReason)
12815 {
12816 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12817 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12818 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12819 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12820 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12821 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12822 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12823 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12824 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12825 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12826 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12827 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12828 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12829 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12830 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12831 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12832 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12833 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12834 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12835 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12836 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12837 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12838 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12839 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12840 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12841 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12842 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12843 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12844 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12845 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12846#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12847 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12848 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12849 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12850 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12851 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12852 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12853 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12854 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12855 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12856 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12857 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12858#else
12859 case VMX_EXIT_VMCLEAR:
12860 case VMX_EXIT_VMLAUNCH:
12861 case VMX_EXIT_VMPTRLD:
12862 case VMX_EXIT_VMPTRST:
12863 case VMX_EXIT_VMREAD:
12864 case VMX_EXIT_VMRESUME:
12865 case VMX_EXIT_VMWRITE:
12866 case VMX_EXIT_VMXOFF:
12867 case VMX_EXIT_VMXON:
12868 case VMX_EXIT_INVVPID:
12869 case VMX_EXIT_INVEPT:
12870 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12871#endif
12872
12873 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12874 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12875 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12876
12877 case VMX_EXIT_INIT_SIGNAL:
12878 case VMX_EXIT_SIPI:
12879 case VMX_EXIT_IO_SMI:
12880 case VMX_EXIT_SMI:
12881 case VMX_EXIT_ERR_MSR_LOAD:
12882 case VMX_EXIT_ERR_MACHINE_CHECK:
12883 case VMX_EXIT_PML_FULL:
12884 case VMX_EXIT_VIRTUALIZED_EOI:
12885 case VMX_EXIT_GDTR_IDTR_ACCESS:
12886 case VMX_EXIT_LDTR_TR_ACCESS:
12887 case VMX_EXIT_APIC_WRITE:
12888 case VMX_EXIT_RDRAND:
12889 case VMX_EXIT_RSM:
12890 case VMX_EXIT_VMFUNC:
12891 case VMX_EXIT_ENCLS:
12892 case VMX_EXIT_RDSEED:
12893 case VMX_EXIT_XSAVES:
12894 case VMX_EXIT_XRSTORS:
12895 case VMX_EXIT_UMWAIT:
12896 case VMX_EXIT_TPAUSE:
12897 default:
12898 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12899 }
12900#undef VMEXIT_CALL_RET
12901}
12902#endif /* !HMVMX_USE_FUNCTION_TABLE */
12903
12904
12905#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12906/**
12907 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12908 *
12909 * @returns Strict VBox status code (i.e. informational status codes too).
12910 * @param pVCpu The cross context virtual CPU structure.
12911 * @param pVmxTransient The VMX-transient structure.
12912 */
12913DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12914{
12915 uint32_t const uExitReason = pVmxTransient->uExitReason;
12916 switch (uExitReason)
12917 {
12918 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12919 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12920 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12921 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12922 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12923
12924 /*
12925 * We shouldn't direct host physical interrupts to the nested-guest.
12926 */
12927 case VMX_EXIT_EXT_INT:
12928 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12929
12930 /*
12931 * Instructions that cause VM-exits unconditionally or the condition is
12932 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12933 * happens, it's guaranteed to be a nested-guest VM-exit).
12934 *
12935 * - Provides VM-exit instruction length ONLY.
12936 */
12937 case VMX_EXIT_CPUID: /* Unconditional. */
12938 case VMX_EXIT_VMCALL:
12939 case VMX_EXIT_GETSEC:
12940 case VMX_EXIT_INVD:
12941 case VMX_EXIT_XSETBV:
12942 case VMX_EXIT_VMLAUNCH:
12943 case VMX_EXIT_VMRESUME:
12944 case VMX_EXIT_VMXOFF:
12945 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12946 case VMX_EXIT_VMFUNC:
12947 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12948
12949 /*
12950 * Instructions that cause VM-exits unconditionally or the condition is
12951 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12952 * happens, it's guaranteed to be a nested-guest VM-exit).
12953 *
12954 * - Provides VM-exit instruction length.
12955 * - Provides VM-exit information.
12956 * - Optionally provides Exit qualification.
12957 *
12958 * Since Exit qualification is 0 for all VM-exits where it is not
12959 * applicable, reading and passing it to the guest should produce
12960 * defined behavior.
12961 *
12962 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12963 */
12964 case VMX_EXIT_INVEPT: /* Unconditional. */
12965 case VMX_EXIT_INVVPID:
12966 case VMX_EXIT_VMCLEAR:
12967 case VMX_EXIT_VMPTRLD:
12968 case VMX_EXIT_VMPTRST:
12969 case VMX_EXIT_VMXON:
12970 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12971 case VMX_EXIT_LDTR_TR_ACCESS:
12972 case VMX_EXIT_RDRAND:
12973 case VMX_EXIT_RDSEED:
12974 case VMX_EXIT_XSAVES:
12975 case VMX_EXIT_XRSTORS:
12976 case VMX_EXIT_UMWAIT:
12977 case VMX_EXIT_TPAUSE:
12978 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12979
12980 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12981 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12982 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12983 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12984 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12985 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12986 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12987 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12988 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12989 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12990 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12991 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12992 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12993 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12994 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12995 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12996 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12997 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12998 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12999
13000 case VMX_EXIT_PREEMPT_TIMER:
13001 {
13002 /** @todo NSTVMX: Preempt timer. */
13003 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13004 }
13005
13006 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13007 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13008
13009 case VMX_EXIT_VMREAD:
13010 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13011
13012 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13013 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13014
13015 case VMX_EXIT_INIT_SIGNAL:
13016 case VMX_EXIT_SIPI:
13017 case VMX_EXIT_IO_SMI:
13018 case VMX_EXIT_SMI:
13019 case VMX_EXIT_ERR_MSR_LOAD:
13020 case VMX_EXIT_ERR_MACHINE_CHECK:
13021 case VMX_EXIT_PML_FULL:
13022 case VMX_EXIT_RSM:
13023 default:
13024 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13025 }
13026}
13027#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13028
13029
13030/** @name VM-exit helpers.
13031 * @{
13032 */
13033/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13034/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13035/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13036
13037/** Macro for VM-exits called unexpectedly. */
13038#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13039 do { \
13040 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13041 return VERR_VMX_UNEXPECTED_EXIT; \
13042 } while (0)
13043
13044#ifdef VBOX_STRICT
13045/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13046# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13047 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13048
13049# define HMVMX_ASSERT_PREEMPT_CPUID() \
13050 do { \
13051 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13052 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13053 } while (0)
13054
13055# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13056 do { \
13057 AssertPtr((a_pVCpu)); \
13058 AssertPtr((a_pVmxTransient)); \
13059 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13060 Assert((a_pVmxTransient)->pVmcsInfo); \
13061 Assert(ASMIntAreEnabled()); \
13062 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13063 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13064 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13065 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13066 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13067 HMVMX_ASSERT_PREEMPT_CPUID(); \
13068 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13069 } while (0)
13070
13071# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13072 do { \
13073 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13074 Assert((a_pVmxTransient)->fIsNestedGuest); \
13075 } while (0)
13076
13077# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13078 do { \
13079 Log4Func(("\n")); \
13080 } while (0)
13081#else
13082# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13083 do { \
13084 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13085 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13086 } while (0)
13087
13088# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13089 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13090
13091# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13092#endif
13093
13094#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13095/** Macro that does the necessary privilege checks and intercepted VM-exits for
13096 * guests that attempted to execute a VMX instruction. */
13097# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13098 do \
13099 { \
13100 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13101 if (rcStrictTmp == VINF_SUCCESS) \
13102 { /* likely */ } \
13103 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13104 { \
13105 Assert((a_pVCpu)->hm.s.Event.fPending); \
13106 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13107 return VINF_SUCCESS; \
13108 } \
13109 else \
13110 { \
13111 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13112 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13113 } \
13114 } while (0)
13115
13116/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13117# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13118 do \
13119 { \
13120 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13121 (a_pGCPtrEffAddr)); \
13122 if (rcStrictTmp == VINF_SUCCESS) \
13123 { /* likely */ } \
13124 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13125 { \
13126 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13127 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13128 NOREF(uXcptTmp); \
13129 return VINF_SUCCESS; \
13130 } \
13131 else \
13132 { \
13133 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13134 return rcStrictTmp; \
13135 } \
13136 } while (0)
13137#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13138
13139
13140/**
13141 * Advances the guest RIP by the specified number of bytes.
13142 *
13143 * @param pVCpu The cross context virtual CPU structure.
13144 * @param cbInstr Number of bytes to advance the RIP by.
13145 *
13146 * @remarks No-long-jump zone!!!
13147 */
13148DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13149{
13150 /* Advance the RIP. */
13151 pVCpu->cpum.GstCtx.rip += cbInstr;
13152 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13153
13154 /* Update interrupt inhibition. */
13155 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13156 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13157 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13158}
13159
13160
13161/**
13162 * Advances the guest RIP after reading it from the VMCS.
13163 *
13164 * @returns VBox status code, no informational status codes.
13165 * @param pVCpu The cross context virtual CPU structure.
13166 * @param pVmxTransient The VMX-transient structure.
13167 *
13168 * @remarks No-long-jump zone!!!
13169 */
13170static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13171{
13172 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13173 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13174 AssertRCReturn(rc, rc);
13175
13176 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13177 return VINF_SUCCESS;
13178}
13179
13180
13181/**
13182 * Handle a condition that occurred while delivering an event through the guest or
13183 * nested-guest IDT.
13184 *
13185 * @returns Strict VBox status code (i.e. informational status codes too).
13186 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13187 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13188 * to continue execution of the guest which will delivery the \#DF.
13189 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13190 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13191 *
13192 * @param pVCpu The cross context virtual CPU structure.
13193 * @param pVmxTransient The VMX-transient structure.
13194 *
13195 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13196 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13197 * is due to an EPT violation, PML full or SPP-related event.
13198 *
13199 * @remarks No-long-jump zone!!!
13200 */
13201static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13202{
13203 Assert(!pVCpu->hm.s.Event.fPending);
13204 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13205 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13206 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13207 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13208 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13209
13210 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13211 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13212 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13213 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13214 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13215 {
13216 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13217 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13218
13219 /*
13220 * If the event was a software interrupt (generated with INT n) or a software exception
13221 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13222 * can handle the VM-exit and continue guest execution which will re-execute the
13223 * instruction rather than re-injecting the exception, as that can cause premature
13224 * trips to ring-3 before injection and involve TRPM which currently has no way of
13225 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13226 * the problem).
13227 */
13228 IEMXCPTRAISE enmRaise;
13229 IEMXCPTRAISEINFO fRaiseInfo;
13230 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13231 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13232 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13233 {
13234 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13235 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13236 }
13237 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13238 {
13239 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13240 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13241 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13242
13243 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13244 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13245
13246 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13247
13248 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13249 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13250 {
13251 pVmxTransient->fVectoringPF = true;
13252 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13253 }
13254 }
13255 else
13256 {
13257 /*
13258 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13259 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13260 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13261 */
13262 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13263 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13264 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13265 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13266 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13267 }
13268
13269 /*
13270 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13271 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13272 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13273 * subsequent VM-entry would fail, see @bugref{7445}.
13274 *
13275 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13276 */
13277 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13278 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13279 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13280 && CPUMIsGuestNmiBlocking(pVCpu))
13281 {
13282 CPUMSetGuestNmiBlocking(pVCpu, false);
13283 }
13284
13285 switch (enmRaise)
13286 {
13287 case IEMXCPTRAISE_CURRENT_XCPT:
13288 {
13289 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13290 Assert(rcStrict == VINF_SUCCESS);
13291 break;
13292 }
13293
13294 case IEMXCPTRAISE_PREV_EVENT:
13295 {
13296 uint32_t u32ErrCode;
13297 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13298 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13299 else
13300 u32ErrCode = 0;
13301
13302 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13303 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13304 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13305 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13306
13307 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13308 pVCpu->hm.s.Event.u32ErrCode));
13309 Assert(rcStrict == VINF_SUCCESS);
13310 break;
13311 }
13312
13313 case IEMXCPTRAISE_REEXEC_INSTR:
13314 Assert(rcStrict == VINF_SUCCESS);
13315 break;
13316
13317 case IEMXCPTRAISE_DOUBLE_FAULT:
13318 {
13319 /*
13320 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13321 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13322 */
13323 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13324 {
13325 pVmxTransient->fVectoringDoublePF = true;
13326 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13327 pVCpu->cpum.GstCtx.cr2));
13328 rcStrict = VINF_SUCCESS;
13329 }
13330 else
13331 {
13332 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13333 hmR0VmxSetPendingXcptDF(pVCpu);
13334 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13335 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13336 rcStrict = VINF_HM_DOUBLE_FAULT;
13337 }
13338 break;
13339 }
13340
13341 case IEMXCPTRAISE_TRIPLE_FAULT:
13342 {
13343 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13344 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13345 rcStrict = VINF_EM_RESET;
13346 break;
13347 }
13348
13349 case IEMXCPTRAISE_CPU_HANG:
13350 {
13351 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13352 rcStrict = VERR_EM_GUEST_CPU_HANG;
13353 break;
13354 }
13355
13356 default:
13357 {
13358 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13359 rcStrict = VERR_VMX_IPE_2;
13360 break;
13361 }
13362 }
13363 }
13364 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13365 && !CPUMIsGuestNmiBlocking(pVCpu))
13366 {
13367 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13368 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13369 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13370 {
13371 /*
13372 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13373 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13374 * that virtual NMIs remain blocked until the IRET execution is completed.
13375 *
13376 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13377 */
13378 CPUMSetGuestNmiBlocking(pVCpu, true);
13379 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13380 }
13381 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13382 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13383 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13384 {
13385 /*
13386 * Execution of IRET caused an EPT violation, page-modification log-full event or
13387 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13388 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13389 * that virtual NMIs remain blocked until the IRET execution is completed.
13390 *
13391 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13392 */
13393 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13394 {
13395 CPUMSetGuestNmiBlocking(pVCpu, true);
13396 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13397 }
13398 }
13399 }
13400
13401 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13402 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13403 return rcStrict;
13404}
13405
13406
13407#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13408/**
13409 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13410 * guest attempting to execute a VMX instruction.
13411 *
13412 * @returns Strict VBox status code (i.e. informational status codes too).
13413 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13414 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13415 *
13416 * @param pVCpu The cross context virtual CPU structure.
13417 * @param uExitReason The VM-exit reason.
13418 *
13419 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13420 * @remarks No-long-jump zone!!!
13421 */
13422static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13423{
13424 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13425 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13426
13427 /*
13428 * The physical CPU would have already checked the CPU mode/code segment.
13429 * We shall just assert here for paranoia.
13430 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13431 */
13432 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13433 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13434 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13435
13436 if (uExitReason == VMX_EXIT_VMXON)
13437 {
13438 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13439
13440 /*
13441 * We check CR4.VMXE because it is required to be always set while in VMX operation
13442 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13443 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13444 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13445 */
13446 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13447 {
13448 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13449 hmR0VmxSetPendingXcptUD(pVCpu);
13450 return VINF_HM_PENDING_XCPT;
13451 }
13452 }
13453 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13454 {
13455 /*
13456 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13457 * (other than VMXON), we need to raise a #UD.
13458 */
13459 Log4Func(("Not in VMX root mode -> #UD\n"));
13460 hmR0VmxSetPendingXcptUD(pVCpu);
13461 return VINF_HM_PENDING_XCPT;
13462 }
13463
13464 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13465 return VINF_SUCCESS;
13466}
13467
13468
13469/**
13470 * Decodes the memory operand of an instruction that caused a VM-exit.
13471 *
13472 * The Exit qualification field provides the displacement field for memory
13473 * operand instructions, if any.
13474 *
13475 * @returns Strict VBox status code (i.e. informational status codes too).
13476 * @retval VINF_SUCCESS if the operand was successfully decoded.
13477 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13478 * operand.
13479 * @param pVCpu The cross context virtual CPU structure.
13480 * @param uExitInstrInfo The VM-exit instruction information field.
13481 * @param enmMemAccess The memory operand's access type (read or write).
13482 * @param GCPtrDisp The instruction displacement field, if any. For
13483 * RIP-relative addressing pass RIP + displacement here.
13484 * @param pGCPtrMem Where to store the effective destination memory address.
13485 *
13486 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13487 * virtual-8086 mode hence skips those checks while verifying if the
13488 * segment is valid.
13489 */
13490static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13491 PRTGCPTR pGCPtrMem)
13492{
13493 Assert(pGCPtrMem);
13494 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13495 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13496 | CPUMCTX_EXTRN_CR0);
13497
13498 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13499 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13500 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13501
13502 VMXEXITINSTRINFO ExitInstrInfo;
13503 ExitInstrInfo.u = uExitInstrInfo;
13504 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13505 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13506 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13507 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13508 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13509 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13510 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13511 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13512 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13513
13514 /*
13515 * Validate instruction information.
13516 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13517 */
13518 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13519 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13520 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13521 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13522 AssertLogRelMsgReturn(fIsMemOperand,
13523 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13524
13525 /*
13526 * Compute the complete effective address.
13527 *
13528 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13529 * See AMD spec. 4.5.2 "Segment Registers".
13530 */
13531 RTGCPTR GCPtrMem = GCPtrDisp;
13532 if (fBaseRegValid)
13533 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13534 if (fIdxRegValid)
13535 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13536
13537 RTGCPTR const GCPtrOff = GCPtrMem;
13538 if ( !fIsLongMode
13539 || iSegReg >= X86_SREG_FS)
13540 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13541 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13542
13543 /*
13544 * Validate effective address.
13545 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13546 */
13547 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13548 Assert(cbAccess > 0);
13549 if (fIsLongMode)
13550 {
13551 if (X86_IS_CANONICAL(GCPtrMem))
13552 {
13553 *pGCPtrMem = GCPtrMem;
13554 return VINF_SUCCESS;
13555 }
13556
13557 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13558 * "Data Limit Checks in 64-bit Mode". */
13559 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13560 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13561 return VINF_HM_PENDING_XCPT;
13562 }
13563
13564 /*
13565 * This is a watered down version of iemMemApplySegment().
13566 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13567 * and segment CPL/DPL checks are skipped.
13568 */
13569 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13570 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13571 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13572
13573 /* Check if the segment is present and usable. */
13574 if ( pSel->Attr.n.u1Present
13575 && !pSel->Attr.n.u1Unusable)
13576 {
13577 Assert(pSel->Attr.n.u1DescType);
13578 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13579 {
13580 /* Check permissions for the data segment. */
13581 if ( enmMemAccess == VMXMEMACCESS_WRITE
13582 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13583 {
13584 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13585 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13586 return VINF_HM_PENDING_XCPT;
13587 }
13588
13589 /* Check limits if it's a normal data segment. */
13590 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13591 {
13592 if ( GCPtrFirst32 > pSel->u32Limit
13593 || GCPtrLast32 > pSel->u32Limit)
13594 {
13595 Log4Func(("Data segment limit exceeded. "
13596 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13597 GCPtrLast32, pSel->u32Limit));
13598 if (iSegReg == X86_SREG_SS)
13599 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13600 else
13601 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13602 return VINF_HM_PENDING_XCPT;
13603 }
13604 }
13605 else
13606 {
13607 /* Check limits if it's an expand-down data segment.
13608 Note! The upper boundary is defined by the B bit, not the G bit! */
13609 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13610 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13611 {
13612 Log4Func(("Expand-down data segment limit exceeded. "
13613 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13614 GCPtrLast32, pSel->u32Limit));
13615 if (iSegReg == X86_SREG_SS)
13616 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13617 else
13618 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13619 return VINF_HM_PENDING_XCPT;
13620 }
13621 }
13622 }
13623 else
13624 {
13625 /* Check permissions for the code segment. */
13626 if ( enmMemAccess == VMXMEMACCESS_WRITE
13627 || ( enmMemAccess == VMXMEMACCESS_READ
13628 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13629 {
13630 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13631 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13632 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13633 return VINF_HM_PENDING_XCPT;
13634 }
13635
13636 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13637 if ( GCPtrFirst32 > pSel->u32Limit
13638 || GCPtrLast32 > pSel->u32Limit)
13639 {
13640 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13641 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13642 if (iSegReg == X86_SREG_SS)
13643 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13644 else
13645 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13646 return VINF_HM_PENDING_XCPT;
13647 }
13648 }
13649 }
13650 else
13651 {
13652 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13653 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13654 return VINF_HM_PENDING_XCPT;
13655 }
13656
13657 *pGCPtrMem = GCPtrMem;
13658 return VINF_SUCCESS;
13659}
13660#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13661
13662
13663/**
13664 * VM-exit helper for LMSW.
13665 */
13666static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13667{
13668 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13669 AssertRCReturn(rc, rc);
13670
13671 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13672 AssertMsg( rcStrict == VINF_SUCCESS
13673 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13674
13675 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13676 if (rcStrict == VINF_IEM_RAISED_XCPT)
13677 {
13678 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13679 rcStrict = VINF_SUCCESS;
13680 }
13681
13682 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13683 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13684 return rcStrict;
13685}
13686
13687
13688/**
13689 * VM-exit helper for CLTS.
13690 */
13691static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13692{
13693 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13694 AssertRCReturn(rc, rc);
13695
13696 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13697 AssertMsg( rcStrict == VINF_SUCCESS
13698 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13699
13700 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13701 if (rcStrict == VINF_IEM_RAISED_XCPT)
13702 {
13703 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13704 rcStrict = VINF_SUCCESS;
13705 }
13706
13707 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13708 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13709 return rcStrict;
13710}
13711
13712
13713/**
13714 * VM-exit helper for MOV from CRx (CRx read).
13715 */
13716static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13717{
13718 Assert(iCrReg < 16);
13719 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13720
13721 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13722 AssertRCReturn(rc, rc);
13723
13724 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13725 AssertMsg( rcStrict == VINF_SUCCESS
13726 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13727
13728 if (iGReg == X86_GREG_xSP)
13729 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13730 else
13731 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13732#ifdef VBOX_WITH_STATISTICS
13733 switch (iCrReg)
13734 {
13735 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13736 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13737 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13738 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13739 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13740 }
13741#endif
13742 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13743 return rcStrict;
13744}
13745
13746
13747/**
13748 * VM-exit helper for MOV to CRx (CRx write).
13749 */
13750static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13751{
13752 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13753 AssertRCReturn(rc, rc);
13754
13755 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13756 AssertMsg( rcStrict == VINF_SUCCESS
13757 || rcStrict == VINF_IEM_RAISED_XCPT
13758 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13759
13760 switch (iCrReg)
13761 {
13762 case 0:
13763 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13764 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13765 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13766 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13767 break;
13768
13769 case 2:
13770 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13771 /* Nothing to do here, CR2 it's not part of the VMCS. */
13772 break;
13773
13774 case 3:
13775 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13776 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13777 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13778 break;
13779
13780 case 4:
13781 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13782 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13783 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13784 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13785 break;
13786
13787 case 8:
13788 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13789 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13790 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13791 break;
13792
13793 default:
13794 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13795 break;
13796 }
13797
13798 if (rcStrict == VINF_IEM_RAISED_XCPT)
13799 {
13800 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13801 rcStrict = VINF_SUCCESS;
13802 }
13803 return rcStrict;
13804}
13805
13806
13807/**
13808 * VM-exit exception handler for \#PF (Page-fault exception).
13809 *
13810 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13811 */
13812static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13813{
13814 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13815 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13816 hmR0VmxReadExitQualVmcs(pVmxTransient);
13817
13818 if (!pVM->hm.s.fNestedPaging)
13819 { /* likely */ }
13820 else
13821 {
13822#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13823 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13824#endif
13825 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13826 if (!pVmxTransient->fVectoringDoublePF)
13827 {
13828 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13829 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13830 }
13831 else
13832 {
13833 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13834 Assert(!pVmxTransient->fIsNestedGuest);
13835 hmR0VmxSetPendingXcptDF(pVCpu);
13836 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13837 }
13838 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13839 return VINF_SUCCESS;
13840 }
13841
13842 Assert(!pVmxTransient->fIsNestedGuest);
13843
13844 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13845 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13846 if (pVmxTransient->fVectoringPF)
13847 {
13848 Assert(pVCpu->hm.s.Event.fPending);
13849 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13850 }
13851
13852 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13853 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13854 AssertRCReturn(rc, rc);
13855
13856 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13857 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13858
13859 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13860 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13861
13862 Log4Func(("#PF: rc=%Rrc\n", rc));
13863 if (rc == VINF_SUCCESS)
13864 {
13865 /*
13866 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13867 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13868 */
13869 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13870 TRPMResetTrap(pVCpu);
13871 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13872 return rc;
13873 }
13874
13875 if (rc == VINF_EM_RAW_GUEST_TRAP)
13876 {
13877 if (!pVmxTransient->fVectoringDoublePF)
13878 {
13879 /* It's a guest page fault and needs to be reflected to the guest. */
13880 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13881 TRPMResetTrap(pVCpu);
13882 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13883 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13884 uGstErrorCode, pVmxTransient->uExitQual);
13885 }
13886 else
13887 {
13888 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13889 TRPMResetTrap(pVCpu);
13890 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13891 hmR0VmxSetPendingXcptDF(pVCpu);
13892 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13893 }
13894
13895 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13896 return VINF_SUCCESS;
13897 }
13898
13899 TRPMResetTrap(pVCpu);
13900 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13901 return rc;
13902}
13903
13904
13905/**
13906 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13907 *
13908 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13909 */
13910static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13911{
13912 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13913 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13914
13915 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13916 AssertRCReturn(rc, rc);
13917
13918 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13919 {
13920 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13921 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13922
13923 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13924 * provides VM-exit instruction length. If this causes problem later,
13925 * disassemble the instruction like it's done on AMD-V. */
13926 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13927 AssertRCReturn(rc2, rc2);
13928 return rc;
13929 }
13930
13931 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13932 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13933 return VINF_SUCCESS;
13934}
13935
13936
13937/**
13938 * VM-exit exception handler for \#BP (Breakpoint exception).
13939 *
13940 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13941 */
13942static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13943{
13944 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13945 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13946
13947 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13948 AssertRCReturn(rc, rc);
13949
13950 if (!pVmxTransient->fIsNestedGuest)
13951 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13952 else
13953 rc = VINF_EM_RAW_GUEST_TRAP;
13954
13955 if (rc == VINF_EM_RAW_GUEST_TRAP)
13956 {
13957 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13958 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13959 rc = VINF_SUCCESS;
13960 }
13961
13962 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13963 return rc;
13964}
13965
13966
13967/**
13968 * VM-exit exception handler for \#AC (Alignment-check exception).
13969 *
13970 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13971 */
13972static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13973{
13974 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13975 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13976
13977 /* Re-inject it. We'll detect any nesting before getting here. */
13978 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13979 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13980 return VINF_SUCCESS;
13981}
13982
13983
13984/**
13985 * VM-exit exception handler for \#DB (Debug exception).
13986 *
13987 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13988 */
13989static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13990{
13991 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13992 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13993
13994 /*
13995 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13996 */
13997 hmR0VmxReadExitQualVmcs(pVmxTransient);
13998
13999 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14000 uint64_t const uDR6 = X86_DR6_INIT_VAL
14001 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14002 | X86_DR6_BD | X86_DR6_BS));
14003
14004 int rc;
14005 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14006 if (!pVmxTransient->fIsNestedGuest)
14007 {
14008 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14009
14010 /*
14011 * Prevents stepping twice over the same instruction when the guest is stepping using
14012 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14013 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14014 */
14015 if ( rc == VINF_EM_DBG_STEPPED
14016 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14017 {
14018 Assert(pVCpu->hm.s.fSingleInstruction);
14019 rc = VINF_EM_RAW_GUEST_TRAP;
14020 }
14021 }
14022 else
14023 rc = VINF_EM_RAW_GUEST_TRAP;
14024 Log6Func(("rc=%Rrc\n", rc));
14025 if (rc == VINF_EM_RAW_GUEST_TRAP)
14026 {
14027 /*
14028 * The exception was for the guest. Update DR6, DR7.GD and
14029 * IA32_DEBUGCTL.LBR before forwarding it.
14030 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14031 */
14032 VMMRZCallRing3Disable(pVCpu);
14033 HM_DISABLE_PREEMPT(pVCpu);
14034
14035 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14036 pCtx->dr[6] |= uDR6;
14037 if (CPUMIsGuestDebugStateActive(pVCpu))
14038 ASMSetDR6(pCtx->dr[6]);
14039
14040 HM_RESTORE_PREEMPT();
14041 VMMRZCallRing3Enable(pVCpu);
14042
14043 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14044 AssertRCReturn(rc, rc);
14045
14046 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14047 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14048
14049 /* Paranoia. */
14050 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14051 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14052
14053 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14054 AssertRC(rc);
14055
14056 /*
14057 * Raise #DB in the guest.
14058 *
14059 * It is important to reflect exactly what the VM-exit gave us (preserving the
14060 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14061 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14062 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14063 *
14064 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14065 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14066 */
14067 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14068 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14069 return VINF_SUCCESS;
14070 }
14071
14072 /*
14073 * Not a guest trap, must be a hypervisor related debug event then.
14074 * Update DR6 in case someone is interested in it.
14075 */
14076 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14077 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14078 CPUMSetHyperDR6(pVCpu, uDR6);
14079
14080 return rc;
14081}
14082
14083
14084/**
14085 * Hacks its way around the lovely mesa driver's backdoor accesses.
14086 *
14087 * @sa hmR0SvmHandleMesaDrvGp.
14088 */
14089static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14090{
14091 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14092 RT_NOREF(pCtx);
14093
14094 /* For now we'll just skip the instruction. */
14095 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14096}
14097
14098
14099/**
14100 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14101 * backdoor logging w/o checking what it is running inside.
14102 *
14103 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14104 * backdoor port and magic numbers loaded in registers.
14105 *
14106 * @returns true if it is, false if it isn't.
14107 * @sa hmR0SvmIsMesaDrvGp.
14108 */
14109DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14110{
14111 /* 0xed: IN eAX,dx */
14112 uint8_t abInstr[1];
14113 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14114 return false;
14115
14116 /* Check that it is #GP(0). */
14117 if (pVmxTransient->uExitIntErrorCode != 0)
14118 return false;
14119
14120 /* Check magic and port. */
14121 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14122 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14123 if (pCtx->rax != UINT32_C(0x564d5868))
14124 return false;
14125 if (pCtx->dx != UINT32_C(0x5658))
14126 return false;
14127
14128 /* Flat ring-3 CS. */
14129 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14130 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14131 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14132 if (pCtx->cs.Attr.n.u2Dpl != 3)
14133 return false;
14134 if (pCtx->cs.u64Base != 0)
14135 return false;
14136
14137 /* Check opcode. */
14138 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14139 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14140 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14141 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14142 if (RT_FAILURE(rc))
14143 return false;
14144 if (abInstr[0] != 0xed)
14145 return false;
14146
14147 return true;
14148}
14149
14150
14151/**
14152 * VM-exit exception handler for \#GP (General-protection exception).
14153 *
14154 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14155 */
14156static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14157{
14158 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14159 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14160
14161 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14162 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14163 if (pVmcsInfo->RealMode.fRealOnV86Active)
14164 { /* likely */ }
14165 else
14166 {
14167#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14168 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14169#endif
14170 /*
14171 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14172 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14173 */
14174 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14175 AssertRCReturn(rc, rc);
14176 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14177 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14178
14179 if ( pVmxTransient->fIsNestedGuest
14180 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14181 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14182 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14183 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14184 else
14185 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14186 return rc;
14187 }
14188
14189 Assert(CPUMIsGuestInRealModeEx(pCtx));
14190 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14191 Assert(!pVmxTransient->fIsNestedGuest);
14192
14193 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14194 AssertRCReturn(rc, rc);
14195
14196 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14197 if (rcStrict == VINF_SUCCESS)
14198 {
14199 if (!CPUMIsGuestInRealModeEx(pCtx))
14200 {
14201 /*
14202 * The guest is no longer in real-mode, check if we can continue executing the
14203 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14204 */
14205 pVmcsInfo->RealMode.fRealOnV86Active = false;
14206 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14207 {
14208 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14209 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14210 }
14211 else
14212 {
14213 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14214 rcStrict = VINF_EM_RESCHEDULE;
14215 }
14216 }
14217 else
14218 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14219 }
14220 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14221 {
14222 rcStrict = VINF_SUCCESS;
14223 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14224 }
14225 return VBOXSTRICTRC_VAL(rcStrict);
14226}
14227
14228
14229/**
14230 * VM-exit exception handler wrapper for all other exceptions that are not handled
14231 * by a specific handler.
14232 *
14233 * This simply re-injects the exception back into the VM without any special
14234 * processing.
14235 *
14236 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14237 */
14238static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14239{
14240 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14241
14242#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14243 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14244 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14245 ("uVector=%#x u32XcptBitmap=%#X32\n",
14246 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14247 NOREF(pVmcsInfo);
14248#endif
14249
14250 /*
14251 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14252 * would have been handled while checking exits due to event delivery.
14253 */
14254 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14255
14256#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14257 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14258 AssertRCReturn(rc, rc);
14259 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14260#endif
14261
14262#ifdef VBOX_WITH_STATISTICS
14263 switch (uVector)
14264 {
14265 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14266 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14267 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14268 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14269 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14270 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14271 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14272 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14273 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14274 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14275 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14276 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14277 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14278 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14279 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14280 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14281 default:
14282 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14283 break;
14284 }
14285#endif
14286
14287 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14288 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14289 NOREF(uVector);
14290
14291 /* Re-inject the original exception into the guest. */
14292 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14293 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14294 return VINF_SUCCESS;
14295}
14296
14297
14298/**
14299 * VM-exit exception handler for all exceptions (except NMIs!).
14300 *
14301 * @remarks This may be called for both guests and nested-guests. Take care to not
14302 * make assumptions and avoid doing anything that is not relevant when
14303 * executing a nested-guest (e.g., Mesa driver hacks).
14304 */
14305static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14306{
14307 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14308
14309 /*
14310 * If this VM-exit occurred while delivering an event through the guest IDT, take
14311 * action based on the return code and additional hints (e.g. for page-faults)
14312 * that will be updated in the VMX transient structure.
14313 */
14314 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14315 if (rcStrict == VINF_SUCCESS)
14316 {
14317 /*
14318 * If an exception caused a VM-exit due to delivery of an event, the original
14319 * event may have to be re-injected into the guest. We shall reinject it and
14320 * continue guest execution. However, page-fault is a complicated case and
14321 * needs additional processing done in hmR0VmxExitXcptPF().
14322 */
14323 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14324 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14325 if ( !pVCpu->hm.s.Event.fPending
14326 || uVector == X86_XCPT_PF)
14327 {
14328 switch (uVector)
14329 {
14330 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14331 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14332 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14333 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14334 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14335 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14336 default:
14337 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14338 }
14339 }
14340 /* else: inject pending event before resuming guest execution. */
14341 }
14342 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14343 {
14344 Assert(pVCpu->hm.s.Event.fPending);
14345 rcStrict = VINF_SUCCESS;
14346 }
14347
14348 return rcStrict;
14349}
14350/** @} */
14351
14352
14353/** @name VM-exit handlers.
14354 * @{
14355 */
14356/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14357/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14358/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14359
14360/**
14361 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14362 */
14363HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14364{
14365 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14366 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14367 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14368 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14369 return VINF_SUCCESS;
14370 return VINF_EM_RAW_INTERRUPT;
14371}
14372
14373
14374/**
14375 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14376 * VM-exit.
14377 */
14378HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14379{
14380 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14381 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14382
14383 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14384
14385 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14386 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14387 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14388
14389 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14390 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14391 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14392 NOREF(pVmcsInfo);
14393
14394 VBOXSTRICTRC rcStrict;
14395 switch (uExitIntType)
14396 {
14397 /*
14398 * Host physical NMIs:
14399 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14400 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14401 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14402 *
14403 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14404 * See Intel spec. 27.5.5 "Updating Non-Register State".
14405 */
14406 case VMX_EXIT_INT_INFO_TYPE_NMI:
14407 {
14408 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14409 break;
14410 }
14411
14412 /*
14413 * Privileged software exceptions (#DB from ICEBP),
14414 * Software exceptions (#BP and #OF),
14415 * Hardware exceptions:
14416 * Process the required exceptions and resume guest execution if possible.
14417 */
14418 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14419 Assert(uVector == X86_XCPT_DB);
14420 RT_FALL_THRU();
14421 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14422 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14423 RT_FALL_THRU();
14424 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14425 {
14426 NOREF(uVector);
14427 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14428 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14429 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14430 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14431
14432 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14433 break;
14434 }
14435
14436 default:
14437 {
14438 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14439 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14440 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14441 break;
14442 }
14443 }
14444
14445 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14446 return rcStrict;
14447}
14448
14449
14450/**
14451 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14452 */
14453HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14454{
14455 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14456
14457 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14458 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14459 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14460
14461 /* Evaluate and deliver pending events and resume guest execution. */
14462 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14463 return VINF_SUCCESS;
14464}
14465
14466
14467/**
14468 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14469 */
14470HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14471{
14472 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14473
14474 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14475 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14476 {
14477 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14478 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14479 }
14480
14481 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14482
14483 /*
14484 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14485 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14486 */
14487 uint32_t fIntrState;
14488 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14489 AssertRC(rc);
14490 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14491 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14492 {
14493 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14494 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14495
14496 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14497 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14498 AssertRC(rc);
14499 }
14500
14501 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14502 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14503
14504 /* Evaluate and deliver pending events and resume guest execution. */
14505 return VINF_SUCCESS;
14506}
14507
14508
14509/**
14510 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14511 */
14512HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14513{
14514 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14515 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14516}
14517
14518
14519/**
14520 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14521 */
14522HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14523{
14524 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14525 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14526}
14527
14528
14529/**
14530 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14531 */
14532HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14533{
14534 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14535
14536 /*
14537 * Get the state we need and update the exit history entry.
14538 */
14539 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14540 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14541
14542 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14543 AssertRCReturn(rc, rc);
14544
14545 VBOXSTRICTRC rcStrict;
14546 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14547 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14548 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14549 if (!pExitRec)
14550 {
14551 /*
14552 * Regular CPUID instruction execution.
14553 */
14554 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14555 if (rcStrict == VINF_SUCCESS)
14556 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14557 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14558 {
14559 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14560 rcStrict = VINF_SUCCESS;
14561 }
14562 }
14563 else
14564 {
14565 /*
14566 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14567 */
14568 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14569 AssertRCReturn(rc2, rc2);
14570
14571 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14572 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14573
14574 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14575 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14576
14577 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14578 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14579 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14580 }
14581 return rcStrict;
14582}
14583
14584
14585/**
14586 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14587 */
14588HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14589{
14590 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14591
14592 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14593 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14594 AssertRCReturn(rc, rc);
14595
14596 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14597 return VINF_EM_RAW_EMULATE_INSTR;
14598
14599 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14600 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14601}
14602
14603
14604/**
14605 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14606 */
14607HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14608{
14609 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14610
14611 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14612 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14613 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14614 AssertRCReturn(rc, rc);
14615
14616 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14617 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14618 {
14619 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14620 we must reset offsetting on VM-entry. See @bugref{6634}. */
14621 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14622 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14623 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14624 }
14625 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14626 {
14627 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14628 rcStrict = VINF_SUCCESS;
14629 }
14630 return rcStrict;
14631}
14632
14633
14634/**
14635 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14636 */
14637HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14638{
14639 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14640
14641 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14642 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14643 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14644 AssertRCReturn(rc, rc);
14645
14646 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14647 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14648 {
14649 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14650 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14651 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14652 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14653 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14654 }
14655 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14656 {
14657 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14658 rcStrict = VINF_SUCCESS;
14659 }
14660 return rcStrict;
14661}
14662
14663
14664/**
14665 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14666 */
14667HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14668{
14669 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14670
14671 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14672 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14673 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14674 AssertRCReturn(rc, rc);
14675
14676 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14677 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14678 if (RT_LIKELY(rc == VINF_SUCCESS))
14679 {
14680 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14681 Assert(pVmxTransient->cbExitInstr == 2);
14682 }
14683 else
14684 {
14685 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14686 rc = VERR_EM_INTERPRETER;
14687 }
14688 return rc;
14689}
14690
14691
14692/**
14693 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14694 */
14695HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14696{
14697 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14698
14699 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14700 if (EMAreHypercallInstructionsEnabled(pVCpu))
14701 {
14702 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14703 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14704 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14705 AssertRCReturn(rc, rc);
14706
14707 /* Perform the hypercall. */
14708 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14709 if (rcStrict == VINF_SUCCESS)
14710 {
14711 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14712 AssertRCReturn(rc, rc);
14713 }
14714 else
14715 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14716 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14717 || RT_FAILURE(rcStrict));
14718
14719 /* If the hypercall changes anything other than guest's general-purpose registers,
14720 we would need to reload the guest changed bits here before VM-entry. */
14721 }
14722 else
14723 Log4Func(("Hypercalls not enabled\n"));
14724
14725 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14726 if (RT_FAILURE(rcStrict))
14727 {
14728 hmR0VmxSetPendingXcptUD(pVCpu);
14729 rcStrict = VINF_SUCCESS;
14730 }
14731
14732 return rcStrict;
14733}
14734
14735
14736/**
14737 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14738 */
14739HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14740{
14741 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14742 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14743
14744 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14745 hmR0VmxReadExitQualVmcs(pVmxTransient);
14746 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14747 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14748 AssertRCReturn(rc, rc);
14749
14750 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14751
14752 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14753 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14754 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14755 {
14756 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14757 rcStrict = VINF_SUCCESS;
14758 }
14759 else
14760 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14761 VBOXSTRICTRC_VAL(rcStrict)));
14762 return rcStrict;
14763}
14764
14765
14766/**
14767 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14768 */
14769HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14770{
14771 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14772
14773 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14774 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14775 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14776 AssertRCReturn(rc, rc);
14777
14778 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14779 if (rcStrict == VINF_SUCCESS)
14780 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14781 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14782 {
14783 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14784 rcStrict = VINF_SUCCESS;
14785 }
14786
14787 return rcStrict;
14788}
14789
14790
14791/**
14792 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14793 */
14794HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14795{
14796 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14797
14798 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14799 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14800 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14801 AssertRCReturn(rc, rc);
14802
14803 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14804 if (RT_SUCCESS(rcStrict))
14805 {
14806 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14807 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14808 rcStrict = VINF_SUCCESS;
14809 }
14810
14811 return rcStrict;
14812}
14813
14814
14815/**
14816 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14817 * VM-exit.
14818 */
14819HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14820{
14821 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14822 return VINF_EM_RESET;
14823}
14824
14825
14826/**
14827 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14828 */
14829HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14830{
14831 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14832
14833 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14834 AssertRCReturn(rc, rc);
14835
14836 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14837 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14838 rc = VINF_SUCCESS;
14839 else
14840 rc = VINF_EM_HALT;
14841
14842 if (rc != VINF_SUCCESS)
14843 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14844 return rc;
14845}
14846
14847
14848/**
14849 * VM-exit handler for instructions that result in a \#UD exception delivered to
14850 * the guest.
14851 */
14852HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14853{
14854 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14855 hmR0VmxSetPendingXcptUD(pVCpu);
14856 return VINF_SUCCESS;
14857}
14858
14859
14860/**
14861 * VM-exit handler for expiry of the VMX-preemption timer.
14862 */
14863HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14864{
14865 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14866
14867 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14868 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14869
14870 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14871 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14872 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14873 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14874 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14875}
14876
14877
14878/**
14879 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14880 */
14881HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14882{
14883 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14884
14885 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14886 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14887 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14888 AssertRCReturn(rc, rc);
14889
14890 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14891 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14892 : HM_CHANGED_RAISED_XCPT_MASK);
14893
14894 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14895 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14896
14897 return rcStrict;
14898}
14899
14900
14901/**
14902 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14903 */
14904HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14905{
14906 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14907
14908 /** @todo Enable the new code after finding a reliably guest test-case. */
14909#if 1
14910 return VERR_EM_INTERPRETER;
14911#else
14912 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14913 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14914 hmR0VmxReadExitQualVmcs(pVmxTransient);
14915 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14916 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14917 AssertRCReturn(rc, rc);
14918
14919 /* Paranoia. Ensure this has a memory operand. */
14920 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14921
14922 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14923 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14924 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14925 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14926
14927 RTGCPTR GCPtrDesc;
14928 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14929
14930 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14931 GCPtrDesc, uType);
14932 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14934 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14935 {
14936 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14937 rcStrict = VINF_SUCCESS;
14938 }
14939 return rcStrict;
14940#endif
14941}
14942
14943
14944/**
14945 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14946 * VM-exit.
14947 */
14948HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14949{
14950 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14951 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14952 AssertRCReturn(rc, rc);
14953
14954 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14955 if (RT_FAILURE(rc))
14956 return rc;
14957
14958 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14959 NOREF(uInvalidReason);
14960
14961#ifdef VBOX_STRICT
14962 uint32_t fIntrState;
14963 uint64_t u64Val;
14964 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14965 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14966 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14967
14968 Log4(("uInvalidReason %u\n", uInvalidReason));
14969 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14970 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14971 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14972
14973 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14974 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14975 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14976 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14977 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14978 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14979 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14980 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14981 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14982 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14983 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14984 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14985 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14986 {
14987 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14988 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14989 }
14990 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14991#endif
14992
14993 return VERR_VMX_INVALID_GUEST_STATE;
14994}
14995
14996/**
14997 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14998 */
14999HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15000{
15001 /*
15002 * Cumulative notes of all recognized but unexpected VM-exits.
15003 *
15004 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15005 * nested-paging is used.
15006 *
15007 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15008 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15009 * this function (and thereby stop VM execution) for handling such instructions.
15010 *
15011 *
15012 * VMX_EXIT_INIT_SIGNAL:
15013 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15014 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15015 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15016 *
15017 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15018 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15019 * See Intel spec. "23.8 Restrictions on VMX operation".
15020 *
15021 * VMX_EXIT_SIPI:
15022 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15023 * activity state is used. We don't make use of it as our guests don't have direct
15024 * access to the host local APIC.
15025 *
15026 * See Intel spec. 25.3 "Other Causes of VM-exits".
15027 *
15028 * VMX_EXIT_IO_SMI:
15029 * VMX_EXIT_SMI:
15030 * This can only happen if we support dual-monitor treatment of SMI, which can be
15031 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15032 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15033 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15034 *
15035 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15036 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15037 *
15038 * VMX_EXIT_ERR_MSR_LOAD:
15039 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15040 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15041 * execution.
15042 *
15043 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15044 *
15045 * VMX_EXIT_ERR_MACHINE_CHECK:
15046 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15047 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15048 * #MC exception abort class exception is raised. We thus cannot assume a
15049 * reasonable chance of continuing any sort of execution and we bail.
15050 *
15051 * See Intel spec. 15.1 "Machine-check Architecture".
15052 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15053 *
15054 * VMX_EXIT_PML_FULL:
15055 * VMX_EXIT_VIRTUALIZED_EOI:
15056 * VMX_EXIT_APIC_WRITE:
15057 * We do not currently support any of these features and thus they are all unexpected
15058 * VM-exits.
15059 *
15060 * VMX_EXIT_GDTR_IDTR_ACCESS:
15061 * VMX_EXIT_LDTR_TR_ACCESS:
15062 * VMX_EXIT_RDRAND:
15063 * VMX_EXIT_RSM:
15064 * VMX_EXIT_VMFUNC:
15065 * VMX_EXIT_ENCLS:
15066 * VMX_EXIT_RDSEED:
15067 * VMX_EXIT_XSAVES:
15068 * VMX_EXIT_XRSTORS:
15069 * VMX_EXIT_UMWAIT:
15070 * VMX_EXIT_TPAUSE:
15071 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15072 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15073 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15074 *
15075 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15076 */
15077 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15078 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15079 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15080}
15081
15082
15083/**
15084 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15085 */
15086HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15087{
15088 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15089
15090 /** @todo Optimize this: We currently drag in the whole MSR state
15091 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15092 * MSRs required. That would require changes to IEM and possibly CPUM too.
15093 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15094 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15095 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15096 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15097 switch (idMsr)
15098 {
15099 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15100 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15101 }
15102
15103 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15104 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15105 AssertRCReturn(rc, rc);
15106
15107 Log4Func(("ecx=%#RX32\n", idMsr));
15108
15109#ifdef VBOX_STRICT
15110 Assert(!pVmxTransient->fIsNestedGuest);
15111 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15112 {
15113 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15114 && idMsr != MSR_K6_EFER)
15115 {
15116 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15117 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15118 }
15119 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15120 {
15121 Assert(pVmcsInfo->pvMsrBitmap);
15122 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15123 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15124 {
15125 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15126 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15127 }
15128 }
15129 }
15130#endif
15131
15132 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15133 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15134 if (rcStrict == VINF_SUCCESS)
15135 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15136 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15137 {
15138 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15139 rcStrict = VINF_SUCCESS;
15140 }
15141 else
15142 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15143
15144 return rcStrict;
15145}
15146
15147
15148/**
15149 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15150 */
15151HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15152{
15153 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15154
15155 /** @todo Optimize this: We currently drag in the whole MSR state
15156 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15157 * MSRs required. That would require changes to IEM and possibly CPUM too.
15158 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15159 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15160 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15161
15162 /*
15163 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15164 * Although we don't need to fetch the base as it will be overwritten shortly, while
15165 * loading guest-state we would also load the entire segment register including limit
15166 * and attributes and thus we need to load them here.
15167 */
15168 switch (idMsr)
15169 {
15170 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15171 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15172 }
15173
15174 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15175 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15176 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15177 AssertRCReturn(rc, rc);
15178
15179 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15180
15181 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15182 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15183
15184 if (rcStrict == VINF_SUCCESS)
15185 {
15186 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15187
15188 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15189 if ( idMsr == MSR_IA32_APICBASE
15190 || ( idMsr >= MSR_IA32_X2APIC_START
15191 && idMsr <= MSR_IA32_X2APIC_END))
15192 {
15193 /*
15194 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15195 * When full APIC register virtualization is implemented we'll have to make
15196 * sure APIC state is saved from the VMCS before IEM changes it.
15197 */
15198 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15199 }
15200 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15201 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15202 else if (idMsr == MSR_K6_EFER)
15203 {
15204 /*
15205 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15206 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15207 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15208 */
15209 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15210 }
15211
15212 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15213 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15214 {
15215 switch (idMsr)
15216 {
15217 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15218 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15219 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15220 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15221 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15222 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15223 default:
15224 {
15225 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15226 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15227 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15228 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15229 break;
15230 }
15231 }
15232 }
15233#ifdef VBOX_STRICT
15234 else
15235 {
15236 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15237 switch (idMsr)
15238 {
15239 case MSR_IA32_SYSENTER_CS:
15240 case MSR_IA32_SYSENTER_EIP:
15241 case MSR_IA32_SYSENTER_ESP:
15242 case MSR_K8_FS_BASE:
15243 case MSR_K8_GS_BASE:
15244 {
15245 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15246 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15247 }
15248
15249 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15250 default:
15251 {
15252 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15253 {
15254 /* EFER MSR writes are always intercepted. */
15255 if (idMsr != MSR_K6_EFER)
15256 {
15257 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15258 idMsr));
15259 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15260 }
15261 }
15262
15263 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15264 {
15265 Assert(pVmcsInfo->pvMsrBitmap);
15266 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15267 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15268 {
15269 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15270 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15271 }
15272 }
15273 break;
15274 }
15275 }
15276 }
15277#endif /* VBOX_STRICT */
15278 }
15279 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15280 {
15281 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15282 rcStrict = VINF_SUCCESS;
15283 }
15284 else
15285 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15286
15287 return rcStrict;
15288}
15289
15290
15291/**
15292 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15293 */
15294HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15295{
15296 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15297
15298 /** @todo The guest has likely hit a contended spinlock. We might want to
15299 * poke a schedule different guest VCPU. */
15300 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15301 if (RT_SUCCESS(rc))
15302 return VINF_EM_RAW_INTERRUPT;
15303
15304 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15305 return rc;
15306}
15307
15308
15309/**
15310 * VM-exit handler for when the TPR value is lowered below the specified
15311 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15312 */
15313HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15314{
15315 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15316 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15317
15318 /*
15319 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15320 * We'll re-evaluate pending interrupts and inject them before the next VM
15321 * entry so we can just continue execution here.
15322 */
15323 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15324 return VINF_SUCCESS;
15325}
15326
15327
15328/**
15329 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15330 * VM-exit.
15331 *
15332 * @retval VINF_SUCCESS when guest execution can continue.
15333 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15334 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15335 * incompatible guest state for VMX execution (real-on-v86 case).
15336 */
15337HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15338{
15339 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15340 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15341
15342 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15343 hmR0VmxReadExitQualVmcs(pVmxTransient);
15344 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15345
15346 VBOXSTRICTRC rcStrict;
15347 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15348 uint64_t const uExitQual = pVmxTransient->uExitQual;
15349 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15350 switch (uAccessType)
15351 {
15352 /*
15353 * MOV to CRx.
15354 */
15355 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15356 {
15357 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15358 AssertRCReturn(rc, rc);
15359
15360 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15361 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15362 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15363 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15364
15365 /*
15366 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15367 * - When nested paging isn't used.
15368 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15369 * - We are executing in the VM debug loop.
15370 */
15371 Assert( iCrReg != 3
15372 || !pVM->hm.s.fNestedPaging
15373 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15374 || pVCpu->hm.s.fUsingDebugLoop);
15375
15376 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15377 Assert( iCrReg != 8
15378 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15379
15380 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15381 AssertMsg( rcStrict == VINF_SUCCESS
15382 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15383
15384 /*
15385 * This is a kludge for handling switches back to real mode when we try to use
15386 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15387 * deal with special selector values, so we have to return to ring-3 and run
15388 * there till the selector values are V86 mode compatible.
15389 *
15390 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15391 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15392 * this function.
15393 */
15394 if ( iCrReg == 0
15395 && rcStrict == VINF_SUCCESS
15396 && !pVM->hm.s.vmx.fUnrestrictedGuest
15397 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15398 && (uOldCr0 & X86_CR0_PE)
15399 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15400 {
15401 /** @todo Check selectors rather than returning all the time. */
15402 Assert(!pVmxTransient->fIsNestedGuest);
15403 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15404 rcStrict = VINF_EM_RESCHEDULE_REM;
15405 }
15406 break;
15407 }
15408
15409 /*
15410 * MOV from CRx.
15411 */
15412 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15413 {
15414 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15415 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15416
15417 /*
15418 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15419 * - When nested paging isn't used.
15420 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15421 * - We are executing in the VM debug loop.
15422 */
15423 Assert( iCrReg != 3
15424 || !pVM->hm.s.fNestedPaging
15425 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15426 || pVCpu->hm.s.fUsingDebugLoop);
15427
15428 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15429 Assert( iCrReg != 8
15430 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15431
15432 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15433 break;
15434 }
15435
15436 /*
15437 * CLTS (Clear Task-Switch Flag in CR0).
15438 */
15439 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15440 {
15441 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15442 break;
15443 }
15444
15445 /*
15446 * LMSW (Load Machine-Status Word into CR0).
15447 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15448 */
15449 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15450 {
15451 RTGCPTR GCPtrEffDst;
15452 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15453 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15454 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15455 if (fMemOperand)
15456 {
15457 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15458 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15459 }
15460 else
15461 GCPtrEffDst = NIL_RTGCPTR;
15462 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15463 break;
15464 }
15465
15466 default:
15467 {
15468 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15469 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15470 }
15471 }
15472
15473 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15474 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15475 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15476
15477 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15478 NOREF(pVM);
15479 return rcStrict;
15480}
15481
15482
15483/**
15484 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15485 * VM-exit.
15486 */
15487HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15488{
15489 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15490 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15491
15492 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15493 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15494 hmR0VmxReadExitQualVmcs(pVmxTransient);
15495 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15496 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15497 | CPUMCTX_EXTRN_EFER);
15498 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15499 AssertRCReturn(rc, rc);
15500
15501 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15502 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15503 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15504 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15505 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15506 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15507 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15508 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15509
15510 /*
15511 * Update exit history to see if this exit can be optimized.
15512 */
15513 VBOXSTRICTRC rcStrict;
15514 PCEMEXITREC pExitRec = NULL;
15515 if ( !fGstStepping
15516 && !fDbgStepping)
15517 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15518 !fIOString
15519 ? !fIOWrite
15520 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15521 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15522 : !fIOWrite
15523 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15524 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15525 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15526 if (!pExitRec)
15527 {
15528 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15529 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15530
15531 uint32_t const cbValue = s_aIOSizes[uIOSize];
15532 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15533 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15534 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15535 if (fIOString)
15536 {
15537 /*
15538 * INS/OUTS - I/O String instruction.
15539 *
15540 * Use instruction-information if available, otherwise fall back on
15541 * interpreting the instruction.
15542 */
15543 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15544 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15545 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15546 if (fInsOutsInfo)
15547 {
15548 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15549 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15550 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15551 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15552 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15553 if (fIOWrite)
15554 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15555 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15556 else
15557 {
15558 /*
15559 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15560 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15561 * See Intel Instruction spec. for "INS".
15562 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15563 */
15564 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15565 }
15566 }
15567 else
15568 rcStrict = IEMExecOne(pVCpu);
15569
15570 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15571 fUpdateRipAlready = true;
15572 }
15573 else
15574 {
15575 /*
15576 * IN/OUT - I/O instruction.
15577 */
15578 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15579 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15580 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15581 if (fIOWrite)
15582 {
15583 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15584 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15585 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15586 && !pCtx->eflags.Bits.u1TF)
15587 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15588 }
15589 else
15590 {
15591 uint32_t u32Result = 0;
15592 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15593 if (IOM_SUCCESS(rcStrict))
15594 {
15595 /* Save result of I/O IN instr. in AL/AX/EAX. */
15596 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15597 }
15598 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15599 && !pCtx->eflags.Bits.u1TF)
15600 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15601 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15602 }
15603 }
15604
15605 if (IOM_SUCCESS(rcStrict))
15606 {
15607 if (!fUpdateRipAlready)
15608 {
15609 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15610 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15611 }
15612
15613 /*
15614 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15615 * while booting Fedora 17 64-bit guest.
15616 *
15617 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15618 */
15619 if (fIOString)
15620 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15621
15622 /*
15623 * If any I/O breakpoints are armed, we need to check if one triggered
15624 * and take appropriate action.
15625 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15626 */
15627 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15628 AssertRCReturn(rc, rc);
15629
15630 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15631 * execution engines about whether hyper BPs and such are pending. */
15632 uint32_t const uDr7 = pCtx->dr[7];
15633 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15634 && X86_DR7_ANY_RW_IO(uDr7)
15635 && (pCtx->cr4 & X86_CR4_DE))
15636 || DBGFBpIsHwIoArmed(pVM)))
15637 {
15638 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15639
15640 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15641 VMMRZCallRing3Disable(pVCpu);
15642 HM_DISABLE_PREEMPT(pVCpu);
15643
15644 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15645
15646 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15647 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15648 {
15649 /* Raise #DB. */
15650 if (fIsGuestDbgActive)
15651 ASMSetDR6(pCtx->dr[6]);
15652 if (pCtx->dr[7] != uDr7)
15653 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15654
15655 hmR0VmxSetPendingXcptDB(pVCpu);
15656 }
15657 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15658 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15659 else if ( rcStrict2 != VINF_SUCCESS
15660 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15661 rcStrict = rcStrict2;
15662 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15663
15664 HM_RESTORE_PREEMPT();
15665 VMMRZCallRing3Enable(pVCpu);
15666 }
15667 }
15668
15669#ifdef VBOX_STRICT
15670 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15671 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15672 Assert(!fIOWrite);
15673 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15674 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15675 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15676 Assert(fIOWrite);
15677 else
15678 {
15679# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15680 * statuses, that the VMM device and some others may return. See
15681 * IOM_SUCCESS() for guidance. */
15682 AssertMsg( RT_FAILURE(rcStrict)
15683 || rcStrict == VINF_SUCCESS
15684 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15685 || rcStrict == VINF_EM_DBG_BREAKPOINT
15686 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15687 || rcStrict == VINF_EM_RAW_TO_R3
15688 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15689# endif
15690 }
15691#endif
15692 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15693 }
15694 else
15695 {
15696 /*
15697 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15698 */
15699 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15700 AssertRCReturn(rc2, rc2);
15701 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15702 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15703 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15704 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15705 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15706 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15707
15708 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15709 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15710
15711 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15712 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15713 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15714 }
15715 return rcStrict;
15716}
15717
15718
15719/**
15720 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15721 * VM-exit.
15722 */
15723HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15724{
15725 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15726
15727 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15728 hmR0VmxReadExitQualVmcs(pVmxTransient);
15729 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15730 {
15731 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15732 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15733 {
15734 uint32_t uErrCode;
15735 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15736 {
15737 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15738 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15739 }
15740 else
15741 uErrCode = 0;
15742
15743 RTGCUINTPTR GCPtrFaultAddress;
15744 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15745 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15746 else
15747 GCPtrFaultAddress = 0;
15748
15749 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15750
15751 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15752 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15753
15754 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15755 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15756 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15757 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15758 }
15759 }
15760
15761 /* Fall back to the interpreter to emulate the task-switch. */
15762 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15763 return VERR_EM_INTERPRETER;
15764}
15765
15766
15767/**
15768 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15769 */
15770HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15771{
15772 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15773
15774 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15775 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15776 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15777 AssertRC(rc);
15778 return VINF_EM_DBG_STEPPED;
15779}
15780
15781
15782/**
15783 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15784 */
15785HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15786{
15787 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15788 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15789
15790 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15791 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15792 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15793 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15794 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15795
15796 /*
15797 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15798 */
15799 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15800 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15801 {
15802 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15803 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15804 {
15805 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15806 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15807 }
15808 }
15809 else
15810 {
15811 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15812 return rcStrict;
15813 }
15814
15815 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15816 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15817 hmR0VmxReadExitQualVmcs(pVmxTransient);
15818 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15819 AssertRCReturn(rc, rc);
15820
15821 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15822 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15823 switch (uAccessType)
15824 {
15825 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15826 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15827 {
15828 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15829 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15830 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15831
15832 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15833 GCPhys &= PAGE_BASE_GC_MASK;
15834 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15835 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15836 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15837
15838 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15839 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15840 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15841 if ( rcStrict == VINF_SUCCESS
15842 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15843 || rcStrict == VERR_PAGE_NOT_PRESENT)
15844 {
15845 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15846 | HM_CHANGED_GUEST_APIC_TPR);
15847 rcStrict = VINF_SUCCESS;
15848 }
15849 break;
15850 }
15851
15852 default:
15853 {
15854 Log4Func(("uAccessType=%#x\n", uAccessType));
15855 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15856 break;
15857 }
15858 }
15859
15860 if (rcStrict != VINF_SUCCESS)
15861 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15862 return rcStrict;
15863}
15864
15865
15866/**
15867 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15868 * VM-exit.
15869 */
15870HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15871{
15872 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15873 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15874
15875 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15876 if (!pVmxTransient->fIsNestedGuest)
15877 {
15878 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15879 if (pVmxTransient->fWasGuestDebugStateActive)
15880 {
15881 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15882 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15883 }
15884
15885 if ( !pVCpu->hm.s.fSingleInstruction
15886 && !pVmxTransient->fWasHyperDebugStateActive)
15887 {
15888 Assert(!DBGFIsStepping(pVCpu));
15889 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15890
15891 /* Don't intercept MOV DRx any more. */
15892 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15893 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15894 AssertRC(rc);
15895
15896 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15897 VMMRZCallRing3Disable(pVCpu);
15898 HM_DISABLE_PREEMPT(pVCpu);
15899
15900 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15901 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15902 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15903
15904 HM_RESTORE_PREEMPT();
15905 VMMRZCallRing3Enable(pVCpu);
15906
15907#ifdef VBOX_WITH_STATISTICS
15908 hmR0VmxReadExitQualVmcs(pVmxTransient);
15909 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15910 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15911 else
15912 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15913#endif
15914 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15915 return VINF_SUCCESS;
15916 }
15917 }
15918
15919 /*
15920 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15921 * The EFER MSR is always up-to-date.
15922 * Update the segment registers and DR7 from the CPU.
15923 */
15924 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15925 hmR0VmxReadExitQualVmcs(pVmxTransient);
15926 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15927 AssertRCReturn(rc, rc);
15928 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15929
15930 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15931 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15932 {
15933 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15934 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15935 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15936 if (RT_SUCCESS(rc))
15937 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15938 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15939 }
15940 else
15941 {
15942 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15943 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15944 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15945 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15946 }
15947
15948 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15949 if (RT_SUCCESS(rc))
15950 {
15951 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15952 AssertRCReturn(rc2, rc2);
15953 return VINF_SUCCESS;
15954 }
15955 return rc;
15956}
15957
15958
15959/**
15960 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15961 * Conditional VM-exit.
15962 */
15963HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15964{
15965 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15966 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15967
15968 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15969 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15970 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15971 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15972 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15973
15974 /*
15975 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15976 */
15977 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15978 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15979 {
15980 /*
15981 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15982 * instruction emulation to inject the original event. Otherwise, injecting the original event
15983 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15984 */
15985 if (!pVCpu->hm.s.Event.fPending)
15986 { /* likely */ }
15987 else
15988 {
15989 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15990#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15991 /** @todo NSTVMX: Think about how this should be handled. */
15992 if (pVmxTransient->fIsNestedGuest)
15993 return VERR_VMX_IPE_3;
15994#endif
15995 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15996 }
15997 }
15998 else
15999 {
16000 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16001 return rcStrict;
16002 }
16003
16004 /*
16005 * Get sufficient state and update the exit history entry.
16006 */
16007 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16008 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16009 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16010 AssertRCReturn(rc, rc);
16011
16012 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16013 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16014 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16015 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16016 if (!pExitRec)
16017 {
16018 /*
16019 * If we succeed, resume guest execution.
16020 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16021 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16022 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16023 * weird case. See @bugref{6043}.
16024 */
16025 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16026 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16027/** @todo bird: We can probably just go straight to IOM here and assume that
16028 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16029 * well. However, we need to address that aliasing workarounds that
16030 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16031 *
16032 * Might also be interesting to see if we can get this done more or
16033 * less locklessly inside IOM. Need to consider the lookup table
16034 * updating and use a bit more carefully first (or do all updates via
16035 * rendezvous) */
16036 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16037 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16038 if ( rcStrict == VINF_SUCCESS
16039 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16040 || rcStrict == VERR_PAGE_NOT_PRESENT)
16041 {
16042 /* Successfully handled MMIO operation. */
16043 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16044 | HM_CHANGED_GUEST_APIC_TPR);
16045 rcStrict = VINF_SUCCESS;
16046 }
16047 }
16048 else
16049 {
16050 /*
16051 * Frequent exit or something needing probing. Call EMHistoryExec.
16052 */
16053 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16054 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16055
16056 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16057 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16058
16059 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16060 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16061 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16062 }
16063 return rcStrict;
16064}
16065
16066
16067/**
16068 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16069 * VM-exit.
16070 */
16071HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16072{
16073 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16074 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16075
16076 hmR0VmxReadExitQualVmcs(pVmxTransient);
16077 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16078 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16079 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16080 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16081 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16082
16083 /*
16084 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16085 */
16086 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16087 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16088 {
16089 /*
16090 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16091 * we shall resolve the nested #PF and re-inject the original event.
16092 */
16093 if (pVCpu->hm.s.Event.fPending)
16094 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16095 }
16096 else
16097 {
16098 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16099 return rcStrict;
16100 }
16101
16102 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16103 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16104 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16105 AssertRCReturn(rc, rc);
16106
16107 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16108 uint64_t const uExitQual = pVmxTransient->uExitQual;
16109 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16110
16111 RTGCUINT uErrorCode = 0;
16112 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16113 uErrorCode |= X86_TRAP_PF_ID;
16114 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16115 uErrorCode |= X86_TRAP_PF_RW;
16116 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16117 uErrorCode |= X86_TRAP_PF_P;
16118
16119 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16120 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16121 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16122
16123 /*
16124 * Handle the pagefault trap for the nested shadow table.
16125 */
16126 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16127 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16128 TRPMResetTrap(pVCpu);
16129
16130 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16131 if ( rcStrict == VINF_SUCCESS
16132 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16133 || rcStrict == VERR_PAGE_NOT_PRESENT)
16134 {
16135 /* Successfully synced our nested page tables. */
16136 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16137 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16138 return VINF_SUCCESS;
16139 }
16140
16141 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16142 return rcStrict;
16143}
16144
16145
16146#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16147/**
16148 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16149 */
16150HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16151{
16152 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16153
16154 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16155 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16156 hmR0VmxReadExitQualVmcs(pVmxTransient);
16157 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16158 | CPUMCTX_EXTRN_HWVIRT
16159 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16160 AssertRCReturn(rc, rc);
16161
16162 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16163
16164 VMXVEXITINFO ExitInfo;
16165 RT_ZERO(ExitInfo);
16166 ExitInfo.uReason = pVmxTransient->uExitReason;
16167 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16168 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16169 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16170 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16171
16172 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16173 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16174 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16175 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16176 {
16177 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16178 rcStrict = VINF_SUCCESS;
16179 }
16180 return rcStrict;
16181}
16182
16183
16184/**
16185 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16186 */
16187HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16188{
16189 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16190
16191 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16192 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16193 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16194 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16195 AssertRCReturn(rc, rc);
16196
16197 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16198
16199 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16200 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16201 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16202 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16203 {
16204 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16205 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16206 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16207 }
16208 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16209 return rcStrict;
16210}
16211
16212
16213/**
16214 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16215 */
16216HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16217{
16218 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16219
16220 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16221 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16222 hmR0VmxReadExitQualVmcs(pVmxTransient);
16223 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16224 | CPUMCTX_EXTRN_HWVIRT
16225 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16226 AssertRCReturn(rc, rc);
16227
16228 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16229
16230 VMXVEXITINFO ExitInfo;
16231 RT_ZERO(ExitInfo);
16232 ExitInfo.uReason = pVmxTransient->uExitReason;
16233 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16234 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16235 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16236 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16237
16238 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16239 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16240 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16241 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16242 {
16243 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16244 rcStrict = VINF_SUCCESS;
16245 }
16246 return rcStrict;
16247}
16248
16249
16250/**
16251 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16252 */
16253HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16254{
16255 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16256
16257 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16258 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16259 hmR0VmxReadExitQualVmcs(pVmxTransient);
16260 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16261 | CPUMCTX_EXTRN_HWVIRT
16262 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16263 AssertRCReturn(rc, rc);
16264
16265 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16266
16267 VMXVEXITINFO ExitInfo;
16268 RT_ZERO(ExitInfo);
16269 ExitInfo.uReason = pVmxTransient->uExitReason;
16270 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16271 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16272 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16273 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16274
16275 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16276 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16277 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16278 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16279 {
16280 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16281 rcStrict = VINF_SUCCESS;
16282 }
16283 return rcStrict;
16284}
16285
16286
16287/**
16288 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16289 */
16290HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16291{
16292 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16293
16294 /*
16295 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16296 * thus might not need to import the shadow VMCS state, it's safer just in case
16297 * code elsewhere dares look at unsynced VMCS fields.
16298 */
16299 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16300 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16301 hmR0VmxReadExitQualVmcs(pVmxTransient);
16302 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16303 | CPUMCTX_EXTRN_HWVIRT
16304 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16305 AssertRCReturn(rc, rc);
16306
16307 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16308
16309 VMXVEXITINFO ExitInfo;
16310 RT_ZERO(ExitInfo);
16311 ExitInfo.uReason = pVmxTransient->uExitReason;
16312 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16313 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16314 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16315 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16316 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16317
16318 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16319 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16320 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16321 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16322 {
16323 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16324 rcStrict = VINF_SUCCESS;
16325 }
16326 return rcStrict;
16327}
16328
16329
16330/**
16331 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16332 */
16333HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16334{
16335 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16336
16337 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16338 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16339 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16340 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16341 AssertRCReturn(rc, rc);
16342
16343 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16344
16345 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16346 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16347 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16348 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16349 {
16350 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16351 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16352 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16353 }
16354 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16355 return rcStrict;
16356}
16357
16358
16359/**
16360 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16361 */
16362HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16363{
16364 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16365
16366 /*
16367 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16368 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16369 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16370 */
16371 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16372 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16373 hmR0VmxReadExitQualVmcs(pVmxTransient);
16374 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16375 | CPUMCTX_EXTRN_HWVIRT
16376 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16377 AssertRCReturn(rc, rc);
16378
16379 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16380
16381 VMXVEXITINFO ExitInfo;
16382 RT_ZERO(ExitInfo);
16383 ExitInfo.uReason = pVmxTransient->uExitReason;
16384 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16385 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16386 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16387 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16388 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16389
16390 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16391 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16392 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16393 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16394 {
16395 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16396 rcStrict = VINF_SUCCESS;
16397 }
16398 return rcStrict;
16399}
16400
16401
16402/**
16403 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16404 */
16405HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16406{
16407 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16408
16409 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16410 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16411 | CPUMCTX_EXTRN_HWVIRT
16412 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16413 AssertRCReturn(rc, rc);
16414
16415 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16416
16417 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16418 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16419 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16420 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16421 {
16422 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16423 rcStrict = VINF_SUCCESS;
16424 }
16425 return rcStrict;
16426}
16427
16428
16429/**
16430 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16431 */
16432HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16433{
16434 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16435
16436 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16437 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16438 hmR0VmxReadExitQualVmcs(pVmxTransient);
16439 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16440 | CPUMCTX_EXTRN_HWVIRT
16441 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16442 AssertRCReturn(rc, rc);
16443
16444 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16445
16446 VMXVEXITINFO ExitInfo;
16447 RT_ZERO(ExitInfo);
16448 ExitInfo.uReason = pVmxTransient->uExitReason;
16449 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16450 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16451 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16452 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16453
16454 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16455 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16456 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16457 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16458 {
16459 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16460 rcStrict = VINF_SUCCESS;
16461 }
16462 return rcStrict;
16463}
16464
16465
16466/**
16467 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16468 */
16469HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16470{
16471 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16472
16473 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16474 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16475 hmR0VmxReadExitQualVmcs(pVmxTransient);
16476 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16477 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16478 AssertRCReturn(rc, rc);
16479
16480 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16481
16482 VMXVEXITINFO ExitInfo;
16483 RT_ZERO(ExitInfo);
16484 ExitInfo.uReason = pVmxTransient->uExitReason;
16485 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16486 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16487 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16488 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16489
16490 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16491 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16492 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16493 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16494 {
16495 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16496 rcStrict = VINF_SUCCESS;
16497 }
16498 return rcStrict;
16499}
16500#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16501/** @} */
16502
16503
16504#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16505/** @name Nested-guest VM-exit handlers.
16506 * @{
16507 */
16508/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16509/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16510/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16511
16512/**
16513 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16514 * Conditional VM-exit.
16515 */
16516HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16517{
16518 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16519
16520 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16521
16522 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16523 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16524 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16525
16526 switch (uExitIntType)
16527 {
16528 /*
16529 * Physical NMIs:
16530 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16531 */
16532 case VMX_EXIT_INT_INFO_TYPE_NMI:
16533 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16534
16535 /*
16536 * Hardware exceptions,
16537 * Software exceptions,
16538 * Privileged software exceptions:
16539 * Figure out if the exception must be delivered to the guest or the nested-guest.
16540 */
16541 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16542 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16543 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16544 {
16545 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16546 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16547 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16548 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16549
16550 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16551 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16552 pVmxTransient->uExitIntErrorCode);
16553 if (fIntercept)
16554 {
16555 /* Exit qualification is required for debug and page-fault exceptions. */
16556 hmR0VmxReadExitQualVmcs(pVmxTransient);
16557
16558 /*
16559 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16560 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16561 * length. However, if delivery of a software interrupt, software exception or privileged
16562 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16563 */
16564 VMXVEXITINFO ExitInfo;
16565 RT_ZERO(ExitInfo);
16566 ExitInfo.uReason = pVmxTransient->uExitReason;
16567 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16568 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16569
16570 VMXVEXITEVENTINFO ExitEventInfo;
16571 RT_ZERO(ExitEventInfo);
16572 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16573 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16574 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16575 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16576
16577#ifdef DEBUG_ramshankar
16578 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16579 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16580 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16581 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16582 {
16583 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16584 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16585 }
16586#endif
16587 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16588 }
16589
16590 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16591 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16592 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16593 }
16594
16595 /*
16596 * Software interrupts:
16597 * VM-exits cannot be caused by software interrupts.
16598 *
16599 * External interrupts:
16600 * This should only happen when "acknowledge external interrupts on VM-exit"
16601 * control is set. However, we never set this when executing a guest or
16602 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16603 * the guest.
16604 */
16605 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16606 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16607 default:
16608 {
16609 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16610 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16611 }
16612 }
16613}
16614
16615
16616/**
16617 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16618 * Unconditional VM-exit.
16619 */
16620HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16621{
16622 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16623 return IEMExecVmxVmexitTripleFault(pVCpu);
16624}
16625
16626
16627/**
16628 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16629 */
16630HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16631{
16632 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16633
16634 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16635 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16636 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16637}
16638
16639
16640/**
16641 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16642 */
16643HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16644{
16645 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16646
16647 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16648 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16649 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16650}
16651
16652
16653/**
16654 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16655 * Unconditional VM-exit.
16656 */
16657HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16658{
16659 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16660
16661 hmR0VmxReadExitQualVmcs(pVmxTransient);
16662 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16663 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16664 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16665
16666 VMXVEXITINFO ExitInfo;
16667 RT_ZERO(ExitInfo);
16668 ExitInfo.uReason = pVmxTransient->uExitReason;
16669 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16670 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16671
16672 VMXVEXITEVENTINFO ExitEventInfo;
16673 RT_ZERO(ExitEventInfo);
16674 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16675 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16676 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16677}
16678
16679
16680/**
16681 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16682 */
16683HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16684{
16685 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16686
16687 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16688 {
16689 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16690 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16691 }
16692 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16693}
16694
16695
16696/**
16697 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16698 */
16699HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16700{
16701 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16702
16703 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16704 {
16705 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16706 hmR0VmxReadExitQualVmcs(pVmxTransient);
16707
16708 VMXVEXITINFO ExitInfo;
16709 RT_ZERO(ExitInfo);
16710 ExitInfo.uReason = pVmxTransient->uExitReason;
16711 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16712 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16713 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16714 }
16715 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16716}
16717
16718
16719/**
16720 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16721 */
16722HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16723{
16724 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16725
16726 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16727 {
16728 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16729 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16730 }
16731 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16732}
16733
16734
16735/**
16736 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16737 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16738 */
16739HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16740{
16741 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16742
16743 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16744 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16745
16746 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16747
16748 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16749 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16750 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16751
16752 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16753 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16754 u64VmcsField &= UINT64_C(0xffffffff);
16755
16756 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16757 {
16758 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16759 hmR0VmxReadExitQualVmcs(pVmxTransient);
16760
16761 VMXVEXITINFO ExitInfo;
16762 RT_ZERO(ExitInfo);
16763 ExitInfo.uReason = pVmxTransient->uExitReason;
16764 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16765 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16766 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16767 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16768 }
16769
16770 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16771 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16772 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16773}
16774
16775
16776/**
16777 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16778 */
16779HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16780{
16781 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16782
16783 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16784 {
16785 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16786 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16787 }
16788
16789 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16790}
16791
16792
16793/**
16794 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16795 * Conditional VM-exit.
16796 */
16797HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16798{
16799 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16800
16801 hmR0VmxReadExitQualVmcs(pVmxTransient);
16802 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16803
16804 VBOXSTRICTRC rcStrict;
16805 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16806 switch (uAccessType)
16807 {
16808 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16809 {
16810 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16811 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16812 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16813 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16814
16815 bool fIntercept;
16816 switch (iCrReg)
16817 {
16818 case 0:
16819 case 4:
16820 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16821 break;
16822
16823 case 3:
16824 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16825 break;
16826
16827 case 8:
16828 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16829 break;
16830
16831 default:
16832 fIntercept = false;
16833 break;
16834 }
16835 if (fIntercept)
16836 {
16837 VMXVEXITINFO ExitInfo;
16838 RT_ZERO(ExitInfo);
16839 ExitInfo.uReason = pVmxTransient->uExitReason;
16840 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16841 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16842 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16843 }
16844 else
16845 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16846 break;
16847 }
16848
16849 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16850 {
16851 /*
16852 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16853 * CR2 reads do not cause a VM-exit.
16854 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16855 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16856 */
16857 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16858 if ( iCrReg == 3
16859 || iCrReg == 8)
16860 {
16861 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16862 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16863 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16864 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16865 {
16866 VMXVEXITINFO ExitInfo;
16867 RT_ZERO(ExitInfo);
16868 ExitInfo.uReason = pVmxTransient->uExitReason;
16869 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16870 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16871 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16872 }
16873 else
16874 {
16875 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16876 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16877 }
16878 }
16879 else
16880 {
16881 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16882 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16883 }
16884 break;
16885 }
16886
16887 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16888 {
16889 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16890 Assert(pVmcsNstGst);
16891 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16892 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16893 if ( (uGstHostMask & X86_CR0_TS)
16894 && (uReadShadow & X86_CR0_TS))
16895 {
16896 VMXVEXITINFO ExitInfo;
16897 RT_ZERO(ExitInfo);
16898 ExitInfo.uReason = pVmxTransient->uExitReason;
16899 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16900 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16901 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16902 }
16903 else
16904 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16905 break;
16906 }
16907
16908 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16909 {
16910 RTGCPTR GCPtrEffDst;
16911 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16912 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16913 if (fMemOperand)
16914 {
16915 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16916 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16917 }
16918 else
16919 GCPtrEffDst = NIL_RTGCPTR;
16920
16921 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
16922 {
16923 VMXVEXITINFO ExitInfo;
16924 RT_ZERO(ExitInfo);
16925 ExitInfo.uReason = pVmxTransient->uExitReason;
16926 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16927 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16928 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16929 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16930 }
16931 else
16932 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16933 break;
16934 }
16935
16936 default:
16937 {
16938 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16939 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16940 }
16941 }
16942
16943 if (rcStrict == VINF_IEM_RAISED_XCPT)
16944 {
16945 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16946 rcStrict = VINF_SUCCESS;
16947 }
16948 return rcStrict;
16949}
16950
16951
16952/**
16953 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16954 * Conditional VM-exit.
16955 */
16956HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16957{
16958 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16959
16960 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16961 {
16962 hmR0VmxReadExitQualVmcs(pVmxTransient);
16963 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16964
16965 VMXVEXITINFO ExitInfo;
16966 RT_ZERO(ExitInfo);
16967 ExitInfo.uReason = pVmxTransient->uExitReason;
16968 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16969 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16970 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16971 }
16972 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16973}
16974
16975
16976/**
16977 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16978 * Conditional VM-exit.
16979 */
16980HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16981{
16982 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16983
16984 hmR0VmxReadExitQualVmcs(pVmxTransient);
16985
16986 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16987 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16988 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16989
16990 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16991 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16992 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16993 {
16994 /*
16995 * IN/OUT instruction:
16996 * - Provides VM-exit instruction length.
16997 *
16998 * INS/OUTS instruction:
16999 * - Provides VM-exit instruction length.
17000 * - Provides Guest-linear address.
17001 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17002 */
17003 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17004 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17005
17006 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17007 pVmxTransient->ExitInstrInfo.u = 0;
17008 pVmxTransient->uGuestLinearAddr = 0;
17009
17010 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17011 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17012 if (fIOString)
17013 {
17014 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17015 if (fVmxInsOutsInfo)
17016 {
17017 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17018 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17019 }
17020 }
17021
17022 VMXVEXITINFO ExitInfo;
17023 RT_ZERO(ExitInfo);
17024 ExitInfo.uReason = pVmxTransient->uExitReason;
17025 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17026 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17027 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17028 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17029 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17030 }
17031 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17032}
17033
17034
17035/**
17036 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17037 */
17038HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17039{
17040 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17041
17042 uint32_t fMsrpm;
17043 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17044 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17045 else
17046 fMsrpm = VMXMSRPM_EXIT_RD;
17047
17048 if (fMsrpm & VMXMSRPM_EXIT_RD)
17049 {
17050 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17051 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17052 }
17053 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17054}
17055
17056
17057/**
17058 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17059 */
17060HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17061{
17062 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17063
17064 uint32_t fMsrpm;
17065 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17066 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17067 else
17068 fMsrpm = VMXMSRPM_EXIT_WR;
17069
17070 if (fMsrpm & VMXMSRPM_EXIT_WR)
17071 {
17072 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17073 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17074 }
17075 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17076}
17077
17078
17079/**
17080 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17081 */
17082HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17083{
17084 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17085
17086 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17087 {
17088 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17089 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17090 }
17091 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17092}
17093
17094
17095/**
17096 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17097 * VM-exit.
17098 */
17099HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17100{
17101 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17102
17103 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17104 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17105 VMXVEXITINFO ExitInfo;
17106 RT_ZERO(ExitInfo);
17107 ExitInfo.uReason = pVmxTransient->uExitReason;
17108 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17109 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17110}
17111
17112
17113/**
17114 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17115 */
17116HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17117{
17118 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17119
17120 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17121 {
17122 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17123 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17124 }
17125 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17126}
17127
17128
17129/**
17130 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17131 */
17132HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17133{
17134 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17135
17136 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17137 * PAUSE when executing a nested-guest? If it does not, we would not need
17138 * to check for the intercepts here. Just call VM-exit... */
17139
17140 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17141 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17142 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17143 {
17144 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17145 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17146 }
17147 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17148}
17149
17150
17151/**
17152 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17153 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17154 */
17155HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17156{
17157 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17158
17159 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17160 {
17161 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17162 VMXVEXITINFO ExitInfo;
17163 RT_ZERO(ExitInfo);
17164 ExitInfo.uReason = pVmxTransient->uExitReason;
17165 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17166 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17167 }
17168 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17169}
17170
17171
17172/**
17173 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17174 * VM-exit.
17175 */
17176HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17177{
17178 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17179
17180 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17181 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17182 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17183 hmR0VmxReadExitQualVmcs(pVmxTransient);
17184
17185 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17186
17187 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17188 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17189
17190 VMXVEXITINFO ExitInfo;
17191 RT_ZERO(ExitInfo);
17192 ExitInfo.uReason = pVmxTransient->uExitReason;
17193 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17194 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17195
17196 VMXVEXITEVENTINFO ExitEventInfo;
17197 RT_ZERO(ExitEventInfo);
17198 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17199 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17200 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17201}
17202
17203
17204/**
17205 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17206 * Conditional VM-exit.
17207 */
17208HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17209{
17210 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17211
17212 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17213 hmR0VmxReadExitQualVmcs(pVmxTransient);
17214 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17215}
17216
17217
17218/**
17219 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17220 * Conditional VM-exit.
17221 */
17222HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17223{
17224 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17225
17226 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17227 hmR0VmxReadExitQualVmcs(pVmxTransient);
17228 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17229}
17230
17231
17232/**
17233 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17234 */
17235HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17236{
17237 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17238
17239 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17240 {
17241 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17242 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17243 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17244 }
17245 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17246}
17247
17248
17249/**
17250 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17251 */
17252HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17253{
17254 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17255
17256 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17257 {
17258 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17259 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17260 }
17261 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17262}
17263
17264
17265/**
17266 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17267 */
17268HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17269{
17270 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17271
17272 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17273 {
17274 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17275 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17276 hmR0VmxReadExitQualVmcs(pVmxTransient);
17277 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17278
17279 VMXVEXITINFO ExitInfo;
17280 RT_ZERO(ExitInfo);
17281 ExitInfo.uReason = pVmxTransient->uExitReason;
17282 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17283 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17284 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17285 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17286 }
17287 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17288}
17289
17290
17291/**
17292 * Nested-guest VM-exit handler for invalid-guest state
17293 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17294 */
17295HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17296{
17297 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17298
17299 /*
17300 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17301 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17302 * Handle it like it's in an invalid guest state of the outer guest.
17303 *
17304 * When the fast path is implemented, this should be changed to cause the corresponding
17305 * nested-guest VM-exit.
17306 */
17307 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17308}
17309
17310
17311/**
17312 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17313 * and only provide the instruction length.
17314 *
17315 * Unconditional VM-exit.
17316 */
17317HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17318{
17319 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17320
17321#ifdef VBOX_STRICT
17322 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17323 switch (pVmxTransient->uExitReason)
17324 {
17325 case VMX_EXIT_ENCLS:
17326 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17327 break;
17328
17329 case VMX_EXIT_VMFUNC:
17330 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17331 break;
17332 }
17333#endif
17334
17335 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17336 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17337}
17338
17339
17340/**
17341 * Nested-guest VM-exit handler for instructions that provide instruction length as
17342 * well as more information.
17343 *
17344 * Unconditional VM-exit.
17345 */
17346HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17347{
17348 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17349
17350#ifdef VBOX_STRICT
17351 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17352 switch (pVmxTransient->uExitReason)
17353 {
17354 case VMX_EXIT_GDTR_IDTR_ACCESS:
17355 case VMX_EXIT_LDTR_TR_ACCESS:
17356 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17357 break;
17358
17359 case VMX_EXIT_RDRAND:
17360 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17361 break;
17362
17363 case VMX_EXIT_RDSEED:
17364 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17365 break;
17366
17367 case VMX_EXIT_XSAVES:
17368 case VMX_EXIT_XRSTORS:
17369 /** @todo NSTVMX: Verify XSS-bitmap. */
17370 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17371 break;
17372
17373 case VMX_EXIT_UMWAIT:
17374 case VMX_EXIT_TPAUSE:
17375 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17376 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17377 break;
17378 }
17379#endif
17380
17381 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17382 hmR0VmxReadExitQualVmcs(pVmxTransient);
17383 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17384
17385 VMXVEXITINFO ExitInfo;
17386 RT_ZERO(ExitInfo);
17387 ExitInfo.uReason = pVmxTransient->uExitReason;
17388 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17389 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17390 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17391 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17392}
17393
17394/** @} */
17395#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17396
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