VirtualBox

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

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

VMM/HMVMXR0: Always use the 64-bit VMX context switcher for 64-bit capable VMs.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 721.4 KB
Line 
1/* $Id: HMVMXR0.cpp 83030 2020-02-10 09:33:49Z 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 supports long mode, always use the 64-bit guest handler, see @bugref{6208#c73}.
4859 * The host is always 64-bit since we no longer support 32-bit hosts.
4860 */
4861 if (pVM->hm.s.fAllow64BitGuests)
4862 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4863 else
4864 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4865
4866 /*
4867 * VM-entry controls.
4868 */
4869 {
4870 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4871 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4872
4873 /*
4874 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4875 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4876 *
4877 * For nested-guests, this is a mandatory VM-entry control. It's also
4878 * required because we do not want to leak host bits to the nested-guest.
4879 */
4880 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4881
4882 /*
4883 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4884 *
4885 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4886 * required to get the nested-guest working with hardware-assisted VMX execution.
4887 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4888 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4889 * here rather than while merging the guest VMCS controls.
4890 */
4891 if (fGstInLongMode)
4892 {
4893 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4894 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4895 }
4896 else
4897 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4898
4899 /*
4900 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4901 *
4902 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4903 * regardless of whether the nested-guest VMCS specifies it because we are free to
4904 * load whatever MSRs we require and we do not need to modify the guest visible copy
4905 * of the VM-entry MSR load area.
4906 */
4907 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4908 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4909 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4910 else
4911 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4912
4913 /*
4914 * The following should -not- be set (since we're not in SMM mode):
4915 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4916 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4917 */
4918
4919 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4920 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4921
4922 if ((fVal & fZap) == fVal)
4923 { /* likely */ }
4924 else
4925 {
4926 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4927 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4928 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4929 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4930 }
4931
4932 /* Commit it to the VMCS. */
4933 if (pVmcsInfo->u32EntryCtls != fVal)
4934 {
4935 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4936 AssertRC(rc);
4937 pVmcsInfo->u32EntryCtls = fVal;
4938 }
4939 }
4940
4941 /*
4942 * VM-exit controls.
4943 */
4944 {
4945 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4946 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4947
4948 /*
4949 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4950 * supported the 1-setting of this bit.
4951 *
4952 * For nested-guests, we set the "save debug controls" as the converse
4953 * "load debug controls" is mandatory for nested-guests anyway.
4954 */
4955 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4956
4957 /*
4958 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4959 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4960 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4961 * hmR0VmxExportHostMsrs().
4962 *
4963 * For nested-guests, we always set this bit as we do not support 32-bit
4964 * hosts.
4965 */
4966 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4967
4968 /*
4969 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4970 *
4971 * For nested-guests, we should use the "save IA32_EFER" control if we also
4972 * used the "load IA32_EFER" control while exporting VM-entry controls.
4973 */
4974 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4975 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4976 {
4977 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4978 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4979 }
4980
4981 /*
4982 * Enable saving of the VMX-preemption timer value on VM-exit.
4983 * For nested-guests, currently not exposed/used.
4984 */
4985 if ( pVM->hm.s.vmx.fUsePreemptTimer
4986 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4987 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4988
4989 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4990 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4991
4992 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4993 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4994 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4995
4996 if ((fVal & fZap) == fVal)
4997 { /* likely */ }
4998 else
4999 {
5000 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5001 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5002 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5003 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5004 }
5005
5006 /* Commit it to the VMCS. */
5007 if (pVmcsInfo->u32ExitCtls != fVal)
5008 {
5009 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5010 AssertRC(rc);
5011 pVmcsInfo->u32ExitCtls = fVal;
5012 }
5013 }
5014
5015 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5016 }
5017 return VINF_SUCCESS;
5018}
5019
5020
5021/**
5022 * Sets the TPR threshold in the VMCS.
5023 *
5024 * @param pVmcsInfo The VMCS info. object.
5025 * @param u32TprThreshold The TPR threshold (task-priority class only).
5026 */
5027DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5028{
5029 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5030 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5031 RT_NOREF(pVmcsInfo);
5032 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5033 AssertRC(rc);
5034}
5035
5036
5037/**
5038 * Exports the guest APIC TPR state into the VMCS.
5039 *
5040 * @param pVCpu The cross context virtual CPU structure.
5041 * @param pVmxTransient The VMX-transient structure.
5042 *
5043 * @remarks No-long-jump zone!!!
5044 */
5045static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5046{
5047 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5048 {
5049 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5050
5051 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5052 if (!pVmxTransient->fIsNestedGuest)
5053 {
5054 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5055 && APICIsEnabled(pVCpu))
5056 {
5057 /*
5058 * Setup TPR shadowing.
5059 */
5060 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5061 {
5062 bool fPendingIntr = false;
5063 uint8_t u8Tpr = 0;
5064 uint8_t u8PendingIntr = 0;
5065 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5066 AssertRC(rc);
5067
5068 /*
5069 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5070 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5071 * priority of the pending interrupt so we can deliver the interrupt. If there
5072 * are no interrupts pending, set threshold to 0 to not cause any
5073 * TPR-below-threshold VM-exits.
5074 */
5075 uint32_t u32TprThreshold = 0;
5076 if (fPendingIntr)
5077 {
5078 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5079 (which is the Task-Priority Class). */
5080 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5081 const uint8_t u8TprPriority = u8Tpr >> 4;
5082 if (u8PendingPriority <= u8TprPriority)
5083 u32TprThreshold = u8PendingPriority;
5084 }
5085
5086 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5087 }
5088 }
5089 }
5090 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5091 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5092 }
5093}
5094
5095
5096/**
5097 * Gets the guest interruptibility-state and updates related force-flags.
5098 *
5099 * @returns Guest's interruptibility-state.
5100 * @param pVCpu The cross context virtual CPU structure.
5101 *
5102 * @remarks No-long-jump zone!!!
5103 */
5104static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5105{
5106 /*
5107 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5108 */
5109 uint32_t fIntrState = 0;
5110 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5111 {
5112 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5113 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5114
5115 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5116 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5117 {
5118 if (pCtx->eflags.Bits.u1IF)
5119 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5120 else
5121 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5122 }
5123 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5124 {
5125 /*
5126 * We can clear the inhibit force flag as even if we go back to the recompiler
5127 * without executing guest code in VT-x, the flag's condition to be cleared is
5128 * met and thus the cleared state is correct.
5129 */
5130 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5131 }
5132 }
5133
5134 /*
5135 * Check if we should inhibit NMI delivery.
5136 */
5137 if (CPUMIsGuestNmiBlocking(pVCpu))
5138 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5139
5140 /*
5141 * Validate.
5142 */
5143#ifdef VBOX_STRICT
5144 /* We don't support block-by-SMI yet.*/
5145 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5146
5147 /* Block-by-STI must not be set when interrupts are disabled. */
5148 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5149 {
5150 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5151 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5152 }
5153#endif
5154
5155 return fIntrState;
5156}
5157
5158
5159/**
5160 * Exports the exception intercepts required for guest execution in the VMCS.
5161 *
5162 * @param pVCpu The cross context virtual CPU structure.
5163 * @param pVmxTransient The VMX-transient structure.
5164 *
5165 * @remarks No-long-jump zone!!!
5166 */
5167static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5168{
5169 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5170 {
5171 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5172 if ( !pVmxTransient->fIsNestedGuest
5173 && pVCpu->hm.s.fGIMTrapXcptUD)
5174 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5175 else
5176 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5177
5178 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5179 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5180 }
5181}
5182
5183
5184/**
5185 * Exports the guest's RIP into the guest-state area in the VMCS.
5186 *
5187 * @param pVCpu The cross context virtual CPU structure.
5188 *
5189 * @remarks No-long-jump zone!!!
5190 */
5191static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5192{
5193 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5194 {
5195 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5196
5197 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5198 AssertRC(rc);
5199
5200 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5201 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5202 }
5203}
5204
5205
5206/**
5207 * Exports the guest's RSP into the guest-state area in the VMCS.
5208 *
5209 * @param pVCpu The cross context virtual CPU structure.
5210 *
5211 * @remarks No-long-jump zone!!!
5212 */
5213static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5214{
5215 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5216 {
5217 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5218
5219 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5220 AssertRC(rc);
5221
5222 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5223 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5224 }
5225}
5226
5227
5228/**
5229 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5230 *
5231 * @param pVCpu The cross context virtual CPU structure.
5232 * @param pVmxTransient The VMX-transient structure.
5233 *
5234 * @remarks No-long-jump zone!!!
5235 */
5236static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5237{
5238 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5239 {
5240 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5241
5242 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5243 Let us assert it as such and use 32-bit VMWRITE. */
5244 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5245 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5246 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5247 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5248
5249 /*
5250 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5251 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5252 * can run the real-mode guest code under Virtual 8086 mode.
5253 */
5254 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5255 if (pVmcsInfo->RealMode.fRealOnV86Active)
5256 {
5257 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5258 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5259 Assert(!pVmxTransient->fIsNestedGuest);
5260 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5261 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5262 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5263 }
5264
5265 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5266 AssertRC(rc);
5267
5268 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5269 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5270 }
5271}
5272
5273
5274#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5275/**
5276 * Copies the nested-guest VMCS to the shadow VMCS.
5277 *
5278 * @returns VBox status code.
5279 * @param pVCpu The cross context virtual CPU structure.
5280 * @param pVmcsInfo The VMCS info. object.
5281 *
5282 * @remarks No-long-jump zone!!!
5283 */
5284static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5285{
5286 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5287 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5288
5289 /*
5290 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5291 * current VMCS, as we may try saving guest lazy MSRs.
5292 *
5293 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5294 * calling the import VMCS code which is currently performing the guest MSR reads
5295 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5296 * and the rest of the VMX leave session machinery.
5297 */
5298 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5299
5300 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5301 if (RT_SUCCESS(rc))
5302 {
5303 /*
5304 * Copy all guest read/write VMCS fields.
5305 *
5306 * We don't check for VMWRITE failures here for performance reasons and
5307 * because they are not expected to fail, barring irrecoverable conditions
5308 * like hardware errors.
5309 */
5310 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5311 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5312 {
5313 uint64_t u64Val;
5314 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5315 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5316 VMXWriteVmcs64(uVmcsField, u64Val);
5317 }
5318
5319 /*
5320 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5321 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5322 */
5323 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5324 {
5325 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5326 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5327 {
5328 uint64_t u64Val;
5329 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5330 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5331 VMXWriteVmcs64(uVmcsField, u64Val);
5332 }
5333 }
5334
5335 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5336 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5337 }
5338
5339 ASMSetFlags(fEFlags);
5340 return rc;
5341}
5342
5343
5344/**
5345 * Copies the shadow VMCS to the nested-guest VMCS.
5346 *
5347 * @returns VBox status code.
5348 * @param pVCpu The cross context virtual CPU structure.
5349 * @param pVmcsInfo The VMCS info. object.
5350 *
5351 * @remarks Called with interrupts disabled.
5352 */
5353static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5354{
5355 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5356 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5357 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5358
5359 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5360 if (RT_SUCCESS(rc))
5361 {
5362 /*
5363 * Copy guest read/write fields from the shadow VMCS.
5364 * Guest read-only fields cannot be modified, so no need to copy them.
5365 *
5366 * We don't check for VMREAD failures here for performance reasons and
5367 * because they are not expected to fail, barring irrecoverable conditions
5368 * like hardware errors.
5369 */
5370 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5371 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5372 {
5373 uint64_t u64Val;
5374 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5375 VMXReadVmcs64(uVmcsField, &u64Val);
5376 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5377 }
5378
5379 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5380 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5381 }
5382 return rc;
5383}
5384
5385
5386/**
5387 * Enables VMCS shadowing for the given VMCS info. object.
5388 *
5389 * @param pVmcsInfo The VMCS info. object.
5390 *
5391 * @remarks No-long-jump zone!!!
5392 */
5393static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5394{
5395 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5396 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5397 {
5398 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5399 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5400 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5401 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5402 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5403 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5404 Log4Func(("Enabled\n"));
5405 }
5406}
5407
5408
5409/**
5410 * Disables VMCS shadowing for the given VMCS info. object.
5411 *
5412 * @param pVmcsInfo The VMCS info. object.
5413 *
5414 * @remarks No-long-jump zone!!!
5415 */
5416static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5417{
5418 /*
5419 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5420 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5421 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5422 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5423 *
5424 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5425 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5426 */
5427 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5428 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5429 {
5430 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5431 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5432 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5433 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5434 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5435 Log4Func(("Disabled\n"));
5436 }
5437}
5438#endif
5439
5440
5441/**
5442 * Exports the guest hardware-virtualization state.
5443 *
5444 * @returns VBox status code.
5445 * @param pVCpu The cross context virtual CPU structure.
5446 * @param pVmxTransient The VMX-transient structure.
5447 *
5448 * @remarks No-long-jump zone!!!
5449 */
5450static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5451{
5452 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5453 {
5454#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5455 /*
5456 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5457 * VMCS shadowing.
5458 */
5459 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5460 {
5461 /*
5462 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5463 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5464 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5465 *
5466 * We check for VMX root mode here in case the guest executes VMXOFF without
5467 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5468 * not clear the current VMCS pointer.
5469 */
5470 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5471 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5472 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5473 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5474 {
5475 /* Paranoia. */
5476 Assert(!pVmxTransient->fIsNestedGuest);
5477
5478 /*
5479 * For performance reasons, also check if the nested hypervisor's current VMCS
5480 * was newly loaded or modified before copying it to the shadow VMCS.
5481 */
5482 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5483 {
5484 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5485 AssertRCReturn(rc, rc);
5486 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5487 }
5488 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5489 }
5490 else
5491 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5492 }
5493#else
5494 NOREF(pVmxTransient);
5495#endif
5496 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5497 }
5498 return VINF_SUCCESS;
5499}
5500
5501
5502/**
5503 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5504 *
5505 * The guest FPU state is always pre-loaded hence we don't need to bother about
5506 * sharing FPU related CR0 bits between the guest and host.
5507 *
5508 * @returns VBox status code.
5509 * @param pVCpu The cross context virtual CPU structure.
5510 * @param pVmxTransient The VMX-transient structure.
5511 *
5512 * @remarks No-long-jump zone!!!
5513 */
5514static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5515{
5516 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5517 {
5518 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5519 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5520
5521 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5522 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5523 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5524 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5525 else
5526 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5527
5528 if (!pVmxTransient->fIsNestedGuest)
5529 {
5530 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5531 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5532 uint64_t const u64ShadowCr0 = u64GuestCr0;
5533 Assert(!RT_HI_U32(u64GuestCr0));
5534
5535 /*
5536 * Setup VT-x's view of the guest CR0.
5537 */
5538 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5539 if (pVM->hm.s.fNestedPaging)
5540 {
5541 if (CPUMIsGuestPagingEnabled(pVCpu))
5542 {
5543 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5544 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5545 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5546 }
5547 else
5548 {
5549 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5550 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5551 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5552 }
5553
5554 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5555 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5556 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5557 }
5558 else
5559 {
5560 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5561 u64GuestCr0 |= X86_CR0_WP;
5562 }
5563
5564 /*
5565 * Guest FPU bits.
5566 *
5567 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5568 * using CR0.TS.
5569 *
5570 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5571 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5572 */
5573 u64GuestCr0 |= X86_CR0_NE;
5574
5575 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5576 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5577
5578 /*
5579 * Update exception intercepts.
5580 */
5581 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5582 if (pVmcsInfo->RealMode.fRealOnV86Active)
5583 {
5584 Assert(PDMVmmDevHeapIsEnabled(pVM));
5585 Assert(pVM->hm.s.vmx.pRealModeTSS);
5586 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5587 }
5588 else
5589 {
5590 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5591 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5592 if (fInterceptMF)
5593 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5594 }
5595
5596 /* Additional intercepts for debugging, define these yourself explicitly. */
5597#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5598 uXcptBitmap |= 0
5599 | RT_BIT(X86_XCPT_BP)
5600 | RT_BIT(X86_XCPT_DE)
5601 | RT_BIT(X86_XCPT_NM)
5602 | RT_BIT(X86_XCPT_TS)
5603 | RT_BIT(X86_XCPT_UD)
5604 | RT_BIT(X86_XCPT_NP)
5605 | RT_BIT(X86_XCPT_SS)
5606 | RT_BIT(X86_XCPT_GP)
5607 | RT_BIT(X86_XCPT_PF)
5608 | RT_BIT(X86_XCPT_MF)
5609 ;
5610#elif defined(HMVMX_ALWAYS_TRAP_PF)
5611 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5612#endif
5613 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5614 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5615 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5616
5617 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5618 u64GuestCr0 |= fSetCr0;
5619 u64GuestCr0 &= fZapCr0;
5620 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5621
5622 /* Commit the CR0 and related fields to the guest VMCS. */
5623 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5624 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5625 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5626 {
5627 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5628 AssertRC(rc);
5629 }
5630 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5631 {
5632 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5633 AssertRC(rc);
5634 }
5635
5636 /* Update our caches. */
5637 pVmcsInfo->u32ProcCtls = uProcCtls;
5638 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5639
5640 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5641 }
5642 else
5643 {
5644 /*
5645 * With nested-guests, we may have extended the guest/host mask here since we
5646 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5647 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5648 * originally supplied. We must copy those bits from the nested-guest CR0 into
5649 * the nested-guest CR0 read-shadow.
5650 */
5651 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5652 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5653 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5654 Assert(!RT_HI_U32(u64GuestCr0));
5655 Assert(u64GuestCr0 & X86_CR0_NE);
5656
5657 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5658 u64GuestCr0 |= fSetCr0;
5659 u64GuestCr0 &= fZapCr0;
5660 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5661
5662 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5663 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5664 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5665
5666 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5667 }
5668
5669 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5670 }
5671
5672 return VINF_SUCCESS;
5673}
5674
5675
5676/**
5677 * Exports the guest control registers (CR3, CR4) into the guest-state area
5678 * in the VMCS.
5679 *
5680 * @returns VBox strict status code.
5681 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5682 * without unrestricted guest access and the VMMDev is not presently
5683 * mapped (e.g. EFI32).
5684 *
5685 * @param pVCpu The cross context virtual CPU structure.
5686 * @param pVmxTransient The VMX-transient structure.
5687 *
5688 * @remarks No-long-jump zone!!!
5689 */
5690static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5691{
5692 int rc = VINF_SUCCESS;
5693 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5694
5695 /*
5696 * Guest CR2.
5697 * It's always loaded in the assembler code. Nothing to do here.
5698 */
5699
5700 /*
5701 * Guest CR3.
5702 */
5703 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5704 {
5705 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5706
5707 if (pVM->hm.s.fNestedPaging)
5708 {
5709 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5710 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5711
5712 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5713 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5714 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5715 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5716
5717 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5718 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5719 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5720
5721 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5722 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5723 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5724 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5725 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5726 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5727 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5728
5729 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5730 AssertRC(rc);
5731
5732 uint64_t u64GuestCr3;
5733 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5734 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5735 || CPUMIsGuestPagingEnabledEx(pCtx))
5736 {
5737 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5738 if (CPUMIsGuestInPAEModeEx(pCtx))
5739 {
5740 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5741 AssertRC(rc);
5742 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5743 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5744 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5745 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5746 }
5747
5748 /*
5749 * The guest's view of its CR3 is unblemished with nested paging when the
5750 * guest is using paging or we have unrestricted guest execution to handle
5751 * the guest when it's not using paging.
5752 */
5753 u64GuestCr3 = pCtx->cr3;
5754 }
5755 else
5756 {
5757 /*
5758 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5759 * thinks it accesses physical memory directly, we use our identity-mapped
5760 * page table to map guest-linear to guest-physical addresses. EPT takes care
5761 * of translating it to host-physical addresses.
5762 */
5763 RTGCPHYS GCPhys;
5764 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5765
5766 /* We obtain it here every time as the guest could have relocated this PCI region. */
5767 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5768 if (RT_SUCCESS(rc))
5769 { /* likely */ }
5770 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5771 {
5772 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5773 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5774 }
5775 else
5776 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5777
5778 u64GuestCr3 = GCPhys;
5779 }
5780
5781 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5782 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5783 AssertRC(rc);
5784 }
5785 else
5786 {
5787 Assert(!pVmxTransient->fIsNestedGuest);
5788 /* Non-nested paging case, just use the hypervisor's CR3. */
5789 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5790
5791 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5792 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5793 AssertRC(rc);
5794 }
5795
5796 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5797 }
5798
5799 /*
5800 * Guest CR4.
5801 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5802 */
5803 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5804 {
5805 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5806 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5807
5808 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5809 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5810
5811 /*
5812 * With nested-guests, we may have extended the guest/host mask here (since we
5813 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5814 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5815 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5816 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5817 */
5818 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5819 uint64_t u64GuestCr4 = pCtx->cr4;
5820 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5821 ? pCtx->cr4
5822 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5823 Assert(!RT_HI_U32(u64GuestCr4));
5824
5825 /*
5826 * Setup VT-x's view of the guest CR4.
5827 *
5828 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5829 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5830 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5831 *
5832 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5833 */
5834 if (pVmcsInfo->RealMode.fRealOnV86Active)
5835 {
5836 Assert(pVM->hm.s.vmx.pRealModeTSS);
5837 Assert(PDMVmmDevHeapIsEnabled(pVM));
5838 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5839 }
5840
5841 if (pVM->hm.s.fNestedPaging)
5842 {
5843 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5844 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5845 {
5846 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5847 u64GuestCr4 |= X86_CR4_PSE;
5848 /* Our identity mapping is a 32-bit page directory. */
5849 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5850 }
5851 /* else use guest CR4.*/
5852 }
5853 else
5854 {
5855 Assert(!pVmxTransient->fIsNestedGuest);
5856
5857 /*
5858 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5859 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5860 */
5861 switch (pVCpu->hm.s.enmShadowMode)
5862 {
5863 case PGMMODE_REAL: /* Real-mode. */
5864 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5865 case PGMMODE_32_BIT: /* 32-bit paging. */
5866 {
5867 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5868 break;
5869 }
5870
5871 case PGMMODE_PAE: /* PAE paging. */
5872 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5873 {
5874 u64GuestCr4 |= X86_CR4_PAE;
5875 break;
5876 }
5877
5878 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5879 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5880 {
5881#ifdef VBOX_WITH_64_BITS_GUESTS
5882 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5883 Assert(u64GuestCr4 & X86_CR4_PAE);
5884 break;
5885#endif
5886 }
5887 default:
5888 AssertFailed();
5889 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5890 }
5891 }
5892
5893 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5894 u64GuestCr4 |= fSetCr4;
5895 u64GuestCr4 &= fZapCr4;
5896
5897 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5898 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5899 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5900
5901 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5902 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5903
5904 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5905
5906 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5907 }
5908 return rc;
5909}
5910
5911
5912/**
5913 * Exports the guest debug registers into the guest-state area in the VMCS.
5914 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5915 *
5916 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5917 *
5918 * @returns VBox status code.
5919 * @param pVCpu The cross context virtual CPU structure.
5920 * @param pVmxTransient The VMX-transient structure.
5921 *
5922 * @remarks No-long-jump zone!!!
5923 */
5924static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5925{
5926 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5927
5928 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5929 * stepping. */
5930 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5931 if (pVmxTransient->fIsNestedGuest)
5932 {
5933 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5934 AssertRC(rc);
5935
5936 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5937 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5938 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5939 AssertRC(rc);
5940 return VINF_SUCCESS;
5941 }
5942
5943#ifdef VBOX_STRICT
5944 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5945 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5946 {
5947 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5948 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5949 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5950 }
5951#endif
5952
5953 bool fSteppingDB = false;
5954 bool fInterceptMovDRx = false;
5955 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5956 if (pVCpu->hm.s.fSingleInstruction)
5957 {
5958 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5959 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5960 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5961 {
5962 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5963 Assert(fSteppingDB == false);
5964 }
5965 else
5966 {
5967 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5968 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5969 pVCpu->hm.s.fClearTrapFlag = true;
5970 fSteppingDB = true;
5971 }
5972 }
5973
5974 uint64_t u64GuestDr7;
5975 if ( fSteppingDB
5976 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5977 {
5978 /*
5979 * Use the combined guest and host DRx values found in the hypervisor register set
5980 * because the hypervisor debugger has breakpoints active or someone is single stepping
5981 * on the host side without a monitor trap flag.
5982 *
5983 * Note! DBGF expects a clean DR6 state before executing guest code.
5984 */
5985 if (!CPUMIsHyperDebugStateActive(pVCpu))
5986 {
5987 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5988 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5989 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5990 }
5991
5992 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5993 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5994 pVCpu->hm.s.fUsingHyperDR7 = true;
5995 fInterceptMovDRx = true;
5996 }
5997 else
5998 {
5999 /*
6000 * If the guest has enabled debug registers, we need to load them prior to
6001 * executing guest code so they'll trigger at the right time.
6002 */
6003 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6004 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6005 {
6006 if (!CPUMIsGuestDebugStateActive(pVCpu))
6007 {
6008 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6009 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6010 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6011 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6012 }
6013 Assert(!fInterceptMovDRx);
6014 }
6015 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6016 {
6017 /*
6018 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6019 * must intercept #DB in order to maintain a correct DR6 guest value, and
6020 * because we need to intercept it to prevent nested #DBs from hanging the
6021 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6022 */
6023 fInterceptMovDRx = true;
6024 }
6025
6026 /* Update DR7 with the actual guest value. */
6027 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6028 pVCpu->hm.s.fUsingHyperDR7 = false;
6029 }
6030
6031 if (fInterceptMovDRx)
6032 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6033 else
6034 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6035
6036 /*
6037 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6038 * monitor-trap flag and update our cache.
6039 */
6040 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6041 {
6042 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6043 AssertRC(rc);
6044 pVmcsInfo->u32ProcCtls = uProcCtls;
6045 }
6046
6047 /*
6048 * Update guest DR7.
6049 */
6050 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6051 AssertRC(rc);
6052
6053 /*
6054 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6055 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6056 *
6057 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6058 */
6059 if (fSteppingDB)
6060 {
6061 Assert(pVCpu->hm.s.fSingleInstruction);
6062 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6063
6064 uint32_t fIntrState = 0;
6065 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6066 AssertRC(rc);
6067
6068 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6069 {
6070 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6071 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6072 AssertRC(rc);
6073 }
6074 }
6075
6076 return VINF_SUCCESS;
6077}
6078
6079
6080#ifdef VBOX_STRICT
6081/**
6082 * Strict function to validate segment registers.
6083 *
6084 * @param pVCpu The cross context virtual CPU structure.
6085 * @param pVmcsInfo The VMCS info. object.
6086 *
6087 * @remarks Will import guest CR0 on strict builds during validation of
6088 * segments.
6089 */
6090static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6091{
6092 /*
6093 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6094 *
6095 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6096 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6097 * unusable bit and doesn't change the guest-context value.
6098 */
6099 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6100 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6101 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6102 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6103 && ( !CPUMIsGuestInRealModeEx(pCtx)
6104 && !CPUMIsGuestInV86ModeEx(pCtx)))
6105 {
6106 /* Protected mode checks */
6107 /* CS */
6108 Assert(pCtx->cs.Attr.n.u1Present);
6109 Assert(!(pCtx->cs.Attr.u & 0xf00));
6110 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6111 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6112 || !(pCtx->cs.Attr.n.u1Granularity));
6113 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6114 || (pCtx->cs.Attr.n.u1Granularity));
6115 /* CS cannot be loaded with NULL in protected mode. */
6116 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6117 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6118 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6119 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6120 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6121 else
6122 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6123 /* SS */
6124 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6125 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6126 if ( !(pCtx->cr0 & X86_CR0_PE)
6127 || pCtx->cs.Attr.n.u4Type == 3)
6128 {
6129 Assert(!pCtx->ss.Attr.n.u2Dpl);
6130 }
6131 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6132 {
6133 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6134 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6135 Assert(pCtx->ss.Attr.n.u1Present);
6136 Assert(!(pCtx->ss.Attr.u & 0xf00));
6137 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6138 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6139 || !(pCtx->ss.Attr.n.u1Granularity));
6140 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6141 || (pCtx->ss.Attr.n.u1Granularity));
6142 }
6143 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6144 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6145 {
6146 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6147 Assert(pCtx->ds.Attr.n.u1Present);
6148 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6149 Assert(!(pCtx->ds.Attr.u & 0xf00));
6150 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6151 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6152 || !(pCtx->ds.Attr.n.u1Granularity));
6153 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6154 || (pCtx->ds.Attr.n.u1Granularity));
6155 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6156 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6157 }
6158 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6159 {
6160 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6161 Assert(pCtx->es.Attr.n.u1Present);
6162 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6163 Assert(!(pCtx->es.Attr.u & 0xf00));
6164 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6165 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6166 || !(pCtx->es.Attr.n.u1Granularity));
6167 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6168 || (pCtx->es.Attr.n.u1Granularity));
6169 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6170 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6171 }
6172 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6173 {
6174 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6175 Assert(pCtx->fs.Attr.n.u1Present);
6176 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6177 Assert(!(pCtx->fs.Attr.u & 0xf00));
6178 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6179 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6180 || !(pCtx->fs.Attr.n.u1Granularity));
6181 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6182 || (pCtx->fs.Attr.n.u1Granularity));
6183 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6184 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6185 }
6186 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6187 {
6188 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6189 Assert(pCtx->gs.Attr.n.u1Present);
6190 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6191 Assert(!(pCtx->gs.Attr.u & 0xf00));
6192 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6193 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6194 || !(pCtx->gs.Attr.n.u1Granularity));
6195 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6196 || (pCtx->gs.Attr.n.u1Granularity));
6197 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6198 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6199 }
6200 /* 64-bit capable CPUs. */
6201 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6202 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6203 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6204 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6205 }
6206 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6207 || ( CPUMIsGuestInRealModeEx(pCtx)
6208 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6209 {
6210 /* Real and v86 mode checks. */
6211 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6212 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6213 if (pVmcsInfo->RealMode.fRealOnV86Active)
6214 {
6215 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6216 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6217 }
6218 else
6219 {
6220 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6221 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6222 }
6223
6224 /* CS */
6225 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6226 Assert(pCtx->cs.u32Limit == 0xffff);
6227 Assert(u32CSAttr == 0xf3);
6228 /* SS */
6229 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6230 Assert(pCtx->ss.u32Limit == 0xffff);
6231 Assert(u32SSAttr == 0xf3);
6232 /* DS */
6233 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6234 Assert(pCtx->ds.u32Limit == 0xffff);
6235 Assert(u32DSAttr == 0xf3);
6236 /* ES */
6237 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6238 Assert(pCtx->es.u32Limit == 0xffff);
6239 Assert(u32ESAttr == 0xf3);
6240 /* FS */
6241 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6242 Assert(pCtx->fs.u32Limit == 0xffff);
6243 Assert(u32FSAttr == 0xf3);
6244 /* GS */
6245 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6246 Assert(pCtx->gs.u32Limit == 0xffff);
6247 Assert(u32GSAttr == 0xf3);
6248 /* 64-bit capable CPUs. */
6249 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6250 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6251 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6252 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6253 }
6254}
6255#endif /* VBOX_STRICT */
6256
6257
6258/**
6259 * Exports a guest segment register into the guest-state area in the VMCS.
6260 *
6261 * @returns VBox status code.
6262 * @param pVCpu The cross context virtual CPU structure.
6263 * @param pVmcsInfo The VMCS info. object.
6264 * @param iSegReg The segment register number (X86_SREG_XXX).
6265 * @param pSelReg Pointer to the segment selector.
6266 *
6267 * @remarks No-long-jump zone!!!
6268 */
6269static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6270{
6271 Assert(iSegReg < X86_SREG_COUNT);
6272 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6273 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6274 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6275 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6276
6277 uint32_t u32Access = pSelReg->Attr.u;
6278 if (pVmcsInfo->RealMode.fRealOnV86Active)
6279 {
6280 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6281 u32Access = 0xf3;
6282 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6283 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6284 RT_NOREF_PV(pVCpu);
6285 }
6286 else
6287 {
6288 /*
6289 * The way to differentiate between whether this is really a null selector or was just
6290 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6291 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6292 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6293 * NULL selectors loaded in protected-mode have their attribute as 0.
6294 */
6295 if (!u32Access)
6296 u32Access = X86DESCATTR_UNUSABLE;
6297 }
6298
6299 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6300 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6301 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6302
6303 /*
6304 * Commit it to the VMCS.
6305 */
6306 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6307 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6308 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6309 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6310 return VINF_SUCCESS;
6311}
6312
6313
6314/**
6315 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6316 * area in the VMCS.
6317 *
6318 * @returns VBox status code.
6319 * @param pVCpu The cross context virtual CPU structure.
6320 * @param pVmxTransient The VMX-transient structure.
6321 *
6322 * @remarks Will import guest CR0 on strict builds during validation of
6323 * segments.
6324 * @remarks No-long-jump zone!!!
6325 */
6326static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6327{
6328 int rc = VERR_INTERNAL_ERROR_5;
6329 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6330 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6331 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6332
6333 /*
6334 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6335 */
6336 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6337 {
6338 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6339 {
6340 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6341 if (pVmcsInfo->RealMode.fRealOnV86Active)
6342 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6343 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6344 AssertRC(rc);
6345 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6346 }
6347
6348 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6349 {
6350 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6351 if (pVmcsInfo->RealMode.fRealOnV86Active)
6352 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6353 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6354 AssertRC(rc);
6355 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6356 }
6357
6358 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6359 {
6360 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6361 if (pVmcsInfo->RealMode.fRealOnV86Active)
6362 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6363 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6364 AssertRC(rc);
6365 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6366 }
6367
6368 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6369 {
6370 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6371 if (pVmcsInfo->RealMode.fRealOnV86Active)
6372 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6373 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6374 AssertRC(rc);
6375 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6376 }
6377
6378 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6379 {
6380 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6381 if (pVmcsInfo->RealMode.fRealOnV86Active)
6382 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6383 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6384 AssertRC(rc);
6385 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6386 }
6387
6388 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6389 {
6390 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6391 if (pVmcsInfo->RealMode.fRealOnV86Active)
6392 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6393 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6394 AssertRC(rc);
6395 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6396 }
6397
6398#ifdef VBOX_STRICT
6399 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6400#endif
6401 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6402 pCtx->cs.Attr.u));
6403 }
6404
6405 /*
6406 * Guest TR.
6407 */
6408 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6409 {
6410 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6411
6412 /*
6413 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6414 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6415 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6416 */
6417 uint16_t u16Sel;
6418 uint32_t u32Limit;
6419 uint64_t u64Base;
6420 uint32_t u32AccessRights;
6421 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6422 {
6423 u16Sel = pCtx->tr.Sel;
6424 u32Limit = pCtx->tr.u32Limit;
6425 u64Base = pCtx->tr.u64Base;
6426 u32AccessRights = pCtx->tr.Attr.u;
6427 }
6428 else
6429 {
6430 Assert(!pVmxTransient->fIsNestedGuest);
6431 Assert(pVM->hm.s.vmx.pRealModeTSS);
6432 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6433
6434 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6435 RTGCPHYS GCPhys;
6436 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6437 AssertRCReturn(rc, rc);
6438
6439 X86DESCATTR DescAttr;
6440 DescAttr.u = 0;
6441 DescAttr.n.u1Present = 1;
6442 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6443
6444 u16Sel = 0;
6445 u32Limit = HM_VTX_TSS_SIZE;
6446 u64Base = GCPhys;
6447 u32AccessRights = DescAttr.u;
6448 }
6449
6450 /* Validate. */
6451 Assert(!(u16Sel & RT_BIT(2)));
6452 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6453 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6454 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6455 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6456 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6457 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6458 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6459 Assert( (u32Limit & 0xfff) == 0xfff
6460 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6461 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6462 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6463
6464 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6465 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6466 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6467 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6468
6469 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6470 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6471 }
6472
6473 /*
6474 * Guest GDTR.
6475 */
6476 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6477 {
6478 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6479
6480 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6481 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6482
6483 /* Validate. */
6484 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6485
6486 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6487 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6488 }
6489
6490 /*
6491 * Guest LDTR.
6492 */
6493 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6494 {
6495 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6496
6497 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6498 uint32_t u32Access;
6499 if ( !pVmxTransient->fIsNestedGuest
6500 && !pCtx->ldtr.Attr.u)
6501 u32Access = X86DESCATTR_UNUSABLE;
6502 else
6503 u32Access = pCtx->ldtr.Attr.u;
6504
6505 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6506 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6507 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6508 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6509
6510 /* Validate. */
6511 if (!(u32Access & X86DESCATTR_UNUSABLE))
6512 {
6513 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6514 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6515 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6516 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6517 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6518 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6519 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6520 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6521 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6522 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6523 }
6524
6525 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6526 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6527 }
6528
6529 /*
6530 * Guest IDTR.
6531 */
6532 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6533 {
6534 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6535
6536 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6537 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6538
6539 /* Validate. */
6540 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6541
6542 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6543 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6544 }
6545
6546 return VINF_SUCCESS;
6547}
6548
6549
6550/**
6551 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6552 * areas.
6553 *
6554 * These MSRs will automatically be loaded to the host CPU on every successful
6555 * VM-entry and stored from the host CPU on every successful VM-exit.
6556 *
6557 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6558 * actual host MSR values are not- updated here for performance reasons. See
6559 * hmR0VmxExportHostMsrs().
6560 *
6561 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6562 *
6563 * @returns VBox status code.
6564 * @param pVCpu The cross context virtual CPU structure.
6565 * @param pVmxTransient The VMX-transient structure.
6566 *
6567 * @remarks No-long-jump zone!!!
6568 */
6569static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6570{
6571 AssertPtr(pVCpu);
6572 AssertPtr(pVmxTransient);
6573
6574 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6575 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6576
6577 /*
6578 * MSRs that we use the auto-load/store MSR area in the VMCS.
6579 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6580 * nothing to do here. The host MSR values are updated when it's safe in
6581 * hmR0VmxLazySaveHostMsrs().
6582 *
6583 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6584 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6585 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6586 * for any MSR that are not part of the lazy MSRs so we do not need to place
6587 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6588 */
6589 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6590 {
6591 /* No auto-load/store MSRs currently. */
6592 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6593 }
6594
6595 /*
6596 * Guest Sysenter MSRs.
6597 */
6598 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6599 {
6600 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6601
6602 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6603 {
6604 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6605 AssertRC(rc);
6606 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6607 }
6608
6609 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6610 {
6611 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6612 AssertRC(rc);
6613 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6614 }
6615
6616 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6617 {
6618 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6619 AssertRC(rc);
6620 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6621 }
6622 }
6623
6624 /*
6625 * Guest/host EFER MSR.
6626 */
6627 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6628 {
6629 /* Whether we are using the VMCS to swap the EFER MSR must have been
6630 determined earlier while exporting VM-entry/VM-exit controls. */
6631 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6632 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6633
6634 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6635 {
6636 /*
6637 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6638 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6639 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6640 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6641 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6642 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6643 * during VM-entry.
6644 */
6645 uint64_t uGuestEferMsr = pCtx->msrEFER;
6646 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6647 {
6648 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6649 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6650 else
6651 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6652 }
6653
6654 /*
6655 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6656 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6657 */
6658 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6659 {
6660 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6661 AssertRC(rc);
6662 }
6663 else
6664 {
6665 /*
6666 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6667 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6668 */
6669 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6670 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6671 AssertRCReturn(rc, rc);
6672 }
6673
6674 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6675 }
6676 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6677 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6678
6679 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6680 }
6681
6682 /*
6683 * Other MSRs.
6684 */
6685 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6686 {
6687 /* Speculation Control (R/W). */
6688 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6689 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6690 {
6691 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6692 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6693 AssertRCReturn(rc, rc);
6694 }
6695
6696 /* Last Branch Record. */
6697 if (pVM->hm.s.vmx.fLbr)
6698 {
6699 uint32_t const idFromIpMsrStart = pVM->hm.s.vmx.idLbrFromIpMsrFirst;
6700 uint32_t const idToIpMsrStart = pVM->hm.s.vmx.idLbrToIpMsrFirst;
6701 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
6702 Assert(cLbrStack <= 32);
6703 for (uint32_t i = 0; i < cLbrStack; i++)
6704 {
6705 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6706 pVmxTransient->pVmcsInfo->au64LbrFromIpMsr[i],
6707 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6708 AssertRCReturn(rc, rc);
6709
6710 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6711 if (idToIpMsrStart != 0)
6712 {
6713 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6714 pVmxTransient->pVmcsInfo->au64LbrToIpMsr[i],
6715 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6716 AssertRCReturn(rc, rc);
6717 }
6718 }
6719
6720 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6721 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hm.s.vmx.idLbrTosMsr,
6722 pVmxTransient->pVmcsInfo->u64LbrTosMsr, false /* fSetReadWrite */,
6723 false /* fUpdateHostMsr */);
6724 AssertRCReturn(rc, rc);
6725 }
6726
6727 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6728 }
6729
6730 return VINF_SUCCESS;
6731}
6732
6733
6734/**
6735 * Wrapper for running the guest code in VT-x.
6736 *
6737 * @returns VBox status code, no informational status codes.
6738 * @param pVCpu The cross context virtual CPU structure.
6739 * @param pVmxTransient The VMX-transient structure.
6740 *
6741 * @remarks No-long-jump zone!!!
6742 */
6743DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6744{
6745 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6746 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6747 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6748
6749 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6750
6751 /*
6752 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6753 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6754 * callee-saved and thus the need for this XMM wrapper.
6755 *
6756 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6757 */
6758 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6759 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6760 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6761#ifdef VBOX_WITH_KERNEL_USING_XMM
6762 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6763#else
6764 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6765#endif
6766 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6767 return rc;
6768}
6769
6770
6771/**
6772 * Reports world-switch error and dumps some useful debug info.
6773 *
6774 * @param pVCpu The cross context virtual CPU structure.
6775 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6776 * @param pVmxTransient The VMX-transient structure (only
6777 * exitReason updated).
6778 */
6779static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6780{
6781 Assert(pVCpu);
6782 Assert(pVmxTransient);
6783 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6784
6785 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6786 switch (rcVMRun)
6787 {
6788 case VERR_VMX_INVALID_VMXON_PTR:
6789 AssertFailed();
6790 break;
6791 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6792 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6793 {
6794 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6795 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6796 AssertRC(rc);
6797 hmR0VmxReadExitQualVmcs(pVmxTransient);
6798
6799 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6800 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6801 Cannot do it here as we may have been long preempted. */
6802
6803#ifdef VBOX_STRICT
6804 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6805 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6806 pVmxTransient->uExitReason));
6807 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6808 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6809 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6810 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6811 else
6812 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6813 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6814 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6815
6816 static struct
6817 {
6818 /** Name of the field to log. */
6819 const char *pszName;
6820 /** The VMCS field. */
6821 uint32_t uVmcsField;
6822 /** Whether host support of this field needs to be checked. */
6823 bool fCheckSupport;
6824 } const s_aVmcsFields[] =
6825 {
6826 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6827 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6828 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6829 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6830 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6831 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6832 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6833 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6834 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6835 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6836 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6837 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6838 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6839 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6840 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6841 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6842 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6843 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6844 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6845 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6846 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6847 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6848 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6849 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6850 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6851 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6852 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6853 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6854 /* The order of selector fields below are fixed! */
6855 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6856 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6857 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6858 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6859 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6860 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6861 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6862 /* End of ordered selector fields. */
6863 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6864 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6865 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6866 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6867 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6868 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6869 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6870 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6871 };
6872
6873 RTGDTR HostGdtr;
6874 ASMGetGDTR(&HostGdtr);
6875
6876 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6877 for (uint32_t i = 0; i < cVmcsFields; i++)
6878 {
6879 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6880
6881 bool fSupported;
6882 if (!s_aVmcsFields[i].fCheckSupport)
6883 fSupported = true;
6884 else
6885 {
6886 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6887 switch (uVmcsField)
6888 {
6889 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6890 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6891 case VMX_VMCS32_CTRL_PROC_EXEC2:
6892 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6893 break;
6894 default:
6895 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6896 }
6897 }
6898
6899 if (fSupported)
6900 {
6901 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6902 switch (uWidth)
6903 {
6904 case VMX_VMCSFIELD_WIDTH_16BIT:
6905 {
6906 uint16_t u16Val;
6907 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6908 AssertRC(rc);
6909 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6910
6911 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6912 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6913 {
6914 if (u16Val < HostGdtr.cbGdt)
6915 {
6916 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6917 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6918 "Host FS", "Host GS", "Host TR" };
6919 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6920 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6921 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6922 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6923 }
6924 else
6925 Log4((" Selector value exceeds GDT limit!\n"));
6926 }
6927 break;
6928 }
6929
6930 case VMX_VMCSFIELD_WIDTH_32BIT:
6931 {
6932 uint32_t u32Val;
6933 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6934 AssertRC(rc);
6935 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6936 break;
6937 }
6938
6939 case VMX_VMCSFIELD_WIDTH_64BIT:
6940 case VMX_VMCSFIELD_WIDTH_NATURAL:
6941 {
6942 uint64_t u64Val;
6943 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6944 AssertRC(rc);
6945 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6946 break;
6947 }
6948 }
6949 }
6950 }
6951
6952 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6953 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6954 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6955 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6956 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6957 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6958#endif /* VBOX_STRICT */
6959 break;
6960 }
6961
6962 default:
6963 /* Impossible */
6964 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6965 break;
6966 }
6967}
6968
6969
6970/**
6971 * Sets up the usage of TSC-offsetting and updates the VMCS.
6972 *
6973 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6974 * VMX-preemption timer.
6975 *
6976 * @returns VBox status code.
6977 * @param pVCpu The cross context virtual CPU structure.
6978 * @param pVmxTransient The VMX-transient structure.
6979 *
6980 * @remarks No-long-jump zone!!!
6981 */
6982static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6983{
6984 bool fOffsettedTsc;
6985 bool fParavirtTsc;
6986 uint64_t uTscOffset;
6987 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6988 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6989
6990 if (pVM->hm.s.vmx.fUsePreemptTimer)
6991 {
6992 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6993
6994 /* Make sure the returned values have sane upper and lower boundaries. */
6995 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6996 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6997 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6998 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6999
7000 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7001 * preemption timers here. We probably need to clamp the preemption timer,
7002 * after converting the timer value to the host. */
7003 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7004 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7005 AssertRC(rc);
7006 }
7007 else
7008 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7009
7010 if (fParavirtTsc)
7011 {
7012 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7013 information before every VM-entry, hence disable it for performance sake. */
7014#if 0
7015 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7016 AssertRC(rc);
7017#endif
7018 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7019 }
7020
7021 if ( fOffsettedTsc
7022 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7023 {
7024 if (pVmxTransient->fIsNestedGuest)
7025 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7026 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7027 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7028 }
7029 else
7030 {
7031 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7032 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7033 }
7034}
7035
7036
7037/**
7038 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7039 * VM-exit interruption info type.
7040 *
7041 * @returns The IEM exception flags.
7042 * @param uVector The event vector.
7043 * @param uVmxEventType The VMX event type.
7044 *
7045 * @remarks This function currently only constructs flags required for
7046 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7047 * and CR2 aspects of an exception are not included).
7048 */
7049static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7050{
7051 uint32_t fIemXcptFlags;
7052 switch (uVmxEventType)
7053 {
7054 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7055 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7056 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7057 break;
7058
7059 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7060 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7061 break;
7062
7063 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7064 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7065 break;
7066
7067 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7068 {
7069 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7070 if (uVector == X86_XCPT_BP)
7071 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7072 else if (uVector == X86_XCPT_OF)
7073 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7074 else
7075 {
7076 fIemXcptFlags = 0;
7077 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7078 }
7079 break;
7080 }
7081
7082 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7083 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7084 break;
7085
7086 default:
7087 fIemXcptFlags = 0;
7088 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7089 break;
7090 }
7091 return fIemXcptFlags;
7092}
7093
7094
7095/**
7096 * Sets an event as a pending event to be injected into the guest.
7097 *
7098 * @param pVCpu The cross context virtual CPU structure.
7099 * @param u32IntInfo The VM-entry interruption-information field.
7100 * @param cbInstr The VM-entry instruction length in bytes (for
7101 * software interrupts, exceptions and privileged
7102 * software exceptions).
7103 * @param u32ErrCode The VM-entry exception error code.
7104 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7105 * page-fault.
7106 */
7107DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7108 RTGCUINTPTR GCPtrFaultAddress)
7109{
7110 Assert(!pVCpu->hm.s.Event.fPending);
7111 pVCpu->hm.s.Event.fPending = true;
7112 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7113 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7114 pVCpu->hm.s.Event.cbInstr = cbInstr;
7115 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7116}
7117
7118
7119/**
7120 * Sets an external interrupt as pending-for-injection into the VM.
7121 *
7122 * @param pVCpu The cross context virtual CPU structure.
7123 * @param u8Interrupt The external interrupt vector.
7124 */
7125DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7126{
7127 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7128 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7129 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7130 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7131 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7132}
7133
7134
7135/**
7136 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7137 *
7138 * @param pVCpu The cross context virtual CPU structure.
7139 */
7140DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7141{
7142 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7143 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7144 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7145 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7146 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7147}
7148
7149
7150/**
7151 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7152 *
7153 * @param pVCpu The cross context virtual CPU structure.
7154 */
7155DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7156{
7157 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7158 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7159 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7160 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7161 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7162}
7163
7164
7165/**
7166 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7167 *
7168 * @param pVCpu The cross context virtual CPU structure.
7169 */
7170DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7171{
7172 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7173 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7174 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7175 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7176 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7177}
7178
7179
7180/**
7181 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7182 *
7183 * @param pVCpu The cross context virtual CPU structure.
7184 */
7185DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7186{
7187 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7188 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7189 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7190 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7191 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7192}
7193
7194
7195#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7196/**
7197 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7198 *
7199 * @param pVCpu The cross context virtual CPU structure.
7200 * @param u32ErrCode The error code for the general-protection exception.
7201 */
7202DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7203{
7204 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7205 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7206 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7207 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7208 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7209}
7210
7211
7212/**
7213 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7214 *
7215 * @param pVCpu The cross context virtual CPU structure.
7216 * @param u32ErrCode The error code for the stack exception.
7217 */
7218DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7219{
7220 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7221 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7222 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7223 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7224 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7225}
7226#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7227
7228
7229/**
7230 * Fixes up attributes for the specified segment register.
7231 *
7232 * @param pVCpu The cross context virtual CPU structure.
7233 * @param pSelReg The segment register that needs fixing.
7234 * @param idxSel The VMCS field for the corresponding segment register.
7235 */
7236static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7237{
7238 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7239
7240 /*
7241 * If VT-x marks the segment as unusable, most other bits remain undefined:
7242 * - For CS the L, D and G bits have meaning.
7243 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7244 * - For the remaining data segments no bits are defined.
7245 *
7246 * The present bit and the unusable bit has been observed to be set at the
7247 * same time (the selector was supposed to be invalid as we started executing
7248 * a V8086 interrupt in ring-0).
7249 *
7250 * What should be important for the rest of the VBox code, is that the P bit is
7251 * cleared. Some of the other VBox code recognizes the unusable bit, but
7252 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7253 * safe side here, we'll strip off P and other bits we don't care about. If
7254 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7255 *
7256 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7257 */
7258#ifdef VBOX_STRICT
7259 uint32_t const uAttr = pSelReg->Attr.u;
7260#endif
7261
7262 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7263 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7264 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7265
7266#ifdef VBOX_STRICT
7267 VMMRZCallRing3Disable(pVCpu);
7268 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7269# ifdef DEBUG_bird
7270 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7271 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7272 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7273# endif
7274 VMMRZCallRing3Enable(pVCpu);
7275 NOREF(uAttr);
7276#endif
7277 RT_NOREF2(pVCpu, idxSel);
7278}
7279
7280
7281/**
7282 * Imports a guest segment register from the current VMCS into the guest-CPU
7283 * context.
7284 *
7285 * @param pVCpu The cross context virtual CPU structure.
7286 * @param iSegReg The segment register number (X86_SREG_XXX).
7287 *
7288 * @remarks Called with interrupts and/or preemption disabled.
7289 */
7290static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7291{
7292 Assert(iSegReg < X86_SREG_COUNT);
7293
7294 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7295 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7296 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7297 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7298
7299 uint16_t u16Sel;
7300 uint64_t u64Base;
7301 uint32_t u32Limit, u32Attr;
7302 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7303 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7304 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7305 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7306
7307 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7308 pSelReg->Sel = u16Sel;
7309 pSelReg->ValidSel = u16Sel;
7310 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7311 pSelReg->u32Limit = u32Limit;
7312 pSelReg->u64Base = u64Base;
7313 pSelReg->Attr.u = u32Attr;
7314 if (u32Attr & X86DESCATTR_UNUSABLE)
7315 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7316}
7317
7318
7319/**
7320 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7321 *
7322 * @param pVCpu The cross context virtual CPU structure.
7323 *
7324 * @remarks Called with interrupts and/or preemption disabled.
7325 */
7326static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7327{
7328 uint16_t u16Sel;
7329 uint64_t u64Base;
7330 uint32_t u32Limit, u32Attr;
7331 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7332 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7333 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7334 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7335
7336 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7337 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7338 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7339 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7340 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7341 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7342 if (u32Attr & X86DESCATTR_UNUSABLE)
7343 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7344}
7345
7346
7347/**
7348 * Imports the guest TR from the current VMCS into the guest-CPU context.
7349 *
7350 * @param pVCpu The cross context virtual CPU structure.
7351 *
7352 * @remarks Called with interrupts and/or preemption disabled.
7353 */
7354static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7355{
7356 uint16_t u16Sel;
7357 uint64_t u64Base;
7358 uint32_t u32Limit, u32Attr;
7359 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7360 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7361 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7362 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7363
7364 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7365 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7366 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7367 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7368 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7369 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7370 /* TR is the only selector that can never be unusable. */
7371 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7372}
7373
7374
7375/**
7376 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7377 *
7378 * @param pVCpu The cross context virtual CPU structure.
7379 *
7380 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7381 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7382 * instead!!!
7383 */
7384static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7385{
7386 uint64_t u64Val;
7387 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7388 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7389 {
7390 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7391 AssertRC(rc);
7392
7393 pCtx->rip = u64Val;
7394 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7395 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7396 }
7397}
7398
7399
7400/**
7401 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7402 *
7403 * @param pVCpu The cross context virtual CPU structure.
7404 * @param pVmcsInfo The VMCS info. object.
7405 *
7406 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7407 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7408 * instead!!!
7409 */
7410static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7411{
7412 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7413 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7414 {
7415 uint64_t u64Val;
7416 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7417 AssertRC(rc);
7418
7419 pCtx->rflags.u64 = u64Val;
7420 if (pVmcsInfo->RealMode.fRealOnV86Active)
7421 {
7422 pCtx->eflags.Bits.u1VM = 0;
7423 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7424 }
7425 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7426 }
7427}
7428
7429
7430/**
7431 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7432 * context.
7433 *
7434 * @param pVCpu The cross context virtual CPU structure.
7435 * @param pVmcsInfo The VMCS info. object.
7436 *
7437 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7438 * do not log!
7439 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7440 * instead!!!
7441 */
7442static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7443{
7444 uint32_t u32Val;
7445 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7446 if (!u32Val)
7447 {
7448 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7449 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7450 CPUMSetGuestNmiBlocking(pVCpu, false);
7451 }
7452 else
7453 {
7454 /*
7455 * We must import RIP here to set our EM interrupt-inhibited state.
7456 * We also import RFLAGS as our code that evaluates pending interrupts
7457 * before VM-entry requires it.
7458 */
7459 hmR0VmxImportGuestRip(pVCpu);
7460 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7461
7462 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7463 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7464 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7465 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7466
7467 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7468 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7469 }
7470}
7471
7472
7473/**
7474 * Worker for VMXR0ImportStateOnDemand.
7475 *
7476 * @returns VBox status code.
7477 * @param pVCpu The cross context virtual CPU structure.
7478 * @param pVmcsInfo The VMCS info. object.
7479 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7480 */
7481static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7482{
7483 int rc = VINF_SUCCESS;
7484 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7485 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7486 uint32_t u32Val;
7487
7488 /*
7489 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7490 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7491 * neither are other host platforms.
7492 *
7493 * Committing this temporarily as it prevents BSOD.
7494 *
7495 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7496 */
7497#ifdef RT_OS_WINDOWS
7498 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7499 return VERR_HM_IPE_1;
7500#endif
7501
7502 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7503
7504 /*
7505 * We disable interrupts to make the updating of the state and in particular
7506 * the fExtrn modification atomic wrt to preemption hooks.
7507 */
7508 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7509
7510 fWhat &= pCtx->fExtrn;
7511 if (fWhat)
7512 {
7513 do
7514 {
7515 if (fWhat & CPUMCTX_EXTRN_RIP)
7516 hmR0VmxImportGuestRip(pVCpu);
7517
7518 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7519 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7520
7521 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7522 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7523
7524 if (fWhat & CPUMCTX_EXTRN_RSP)
7525 {
7526 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7527 AssertRC(rc);
7528 }
7529
7530 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7531 {
7532 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7533 if (fWhat & CPUMCTX_EXTRN_CS)
7534 {
7535 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7536 hmR0VmxImportGuestRip(pVCpu);
7537 if (fRealOnV86Active)
7538 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7539 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7540 }
7541 if (fWhat & CPUMCTX_EXTRN_SS)
7542 {
7543 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7544 if (fRealOnV86Active)
7545 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7546 }
7547 if (fWhat & CPUMCTX_EXTRN_DS)
7548 {
7549 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7550 if (fRealOnV86Active)
7551 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7552 }
7553 if (fWhat & CPUMCTX_EXTRN_ES)
7554 {
7555 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7556 if (fRealOnV86Active)
7557 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7558 }
7559 if (fWhat & CPUMCTX_EXTRN_FS)
7560 {
7561 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7562 if (fRealOnV86Active)
7563 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7564 }
7565 if (fWhat & CPUMCTX_EXTRN_GS)
7566 {
7567 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7568 if (fRealOnV86Active)
7569 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7570 }
7571 }
7572
7573 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7574 {
7575 if (fWhat & CPUMCTX_EXTRN_LDTR)
7576 hmR0VmxImportGuestLdtr(pVCpu);
7577
7578 if (fWhat & CPUMCTX_EXTRN_GDTR)
7579 {
7580 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7581 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7582 pCtx->gdtr.cbGdt = u32Val;
7583 }
7584
7585 /* Guest IDTR. */
7586 if (fWhat & CPUMCTX_EXTRN_IDTR)
7587 {
7588 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7589 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7590 pCtx->idtr.cbIdt = u32Val;
7591 }
7592
7593 /* Guest TR. */
7594 if (fWhat & CPUMCTX_EXTRN_TR)
7595 {
7596 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7597 don't need to import that one. */
7598 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7599 hmR0VmxImportGuestTr(pVCpu);
7600 }
7601 }
7602
7603 if (fWhat & CPUMCTX_EXTRN_DR7)
7604 {
7605 if (!pVCpu->hm.s.fUsingHyperDR7)
7606 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7607 }
7608
7609 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7610 {
7611 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7612 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7613 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7614 pCtx->SysEnter.cs = u32Val;
7615 }
7616
7617 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7618 {
7619 if ( pVM->hm.s.fAllow64BitGuests
7620 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7621 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7622 }
7623
7624 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7625 {
7626 if ( pVM->hm.s.fAllow64BitGuests
7627 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7628 {
7629 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7630 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7631 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7632 }
7633 }
7634
7635 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7636 {
7637 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7638 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7639 Assert(pMsrs);
7640 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7641 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7642 for (uint32_t i = 0; i < cMsrs; i++)
7643 {
7644 uint32_t const idMsr = pMsrs[i].u32Msr;
7645 switch (idMsr)
7646 {
7647 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7648 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7649 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7650 default:
7651 {
7652 uint32_t idxLbrMsr;
7653 if (pVM->hm.s.vmx.fLbr)
7654 {
7655 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7656 {
7657 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7658 pVmcsInfo->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7659 break;
7660 }
7661 else if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7662 {
7663 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfo->au64LbrFromIpMsr));
7664 pVmcsInfo->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7665 break;
7666 }
7667 else if (idMsr == pVM->hm.s.vmx.idLbrTosMsr)
7668 {
7669 pVmcsInfo->u64LbrTosMsr = pMsrs[i].u64Value;
7670 break;
7671 }
7672 /* Fallthru (no break) */
7673 }
7674 pCtx->fExtrn = 0;
7675 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7676 ASMSetFlags(fEFlags);
7677 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7678 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7679 }
7680 }
7681 }
7682 }
7683
7684 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7685 {
7686 if (fWhat & CPUMCTX_EXTRN_CR0)
7687 {
7688 uint64_t u64Cr0;
7689 uint64_t u64Shadow;
7690 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7691 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7692#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7693 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7694 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7695#else
7696 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7697 {
7698 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7699 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7700 }
7701 else
7702 {
7703 /*
7704 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7705 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7706 * re-construct CR0. See @bugref{9180#c95} for details.
7707 */
7708 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7709 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7710 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7711 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7712 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7713 }
7714#endif
7715 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7716 CPUMSetGuestCR0(pVCpu, u64Cr0);
7717 VMMRZCallRing3Enable(pVCpu);
7718 }
7719
7720 if (fWhat & CPUMCTX_EXTRN_CR4)
7721 {
7722 uint64_t u64Cr4;
7723 uint64_t u64Shadow;
7724 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7725 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7726#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7727 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7728 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7729#else
7730 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7731 {
7732 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7733 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7734 }
7735 else
7736 {
7737 /*
7738 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7739 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7740 * re-construct CR4. See @bugref{9180#c95} for details.
7741 */
7742 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7743 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7744 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7745 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7746 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7747 }
7748#endif
7749 pCtx->cr4 = u64Cr4;
7750 }
7751
7752 if (fWhat & CPUMCTX_EXTRN_CR3)
7753 {
7754 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7755 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7756 || ( pVM->hm.s.fNestedPaging
7757 && CPUMIsGuestPagingEnabledEx(pCtx)))
7758 {
7759 uint64_t u64Cr3;
7760 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7761 if (pCtx->cr3 != u64Cr3)
7762 {
7763 pCtx->cr3 = u64Cr3;
7764 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7765 }
7766
7767 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7768 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7769 if (CPUMIsGuestInPAEModeEx(pCtx))
7770 {
7771 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7772 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7773 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7774 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7775 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7776 }
7777 }
7778 }
7779 }
7780
7781#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7782 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7783 {
7784 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7785 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7786 {
7787 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7788 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7789 if (RT_SUCCESS(rc))
7790 { /* likely */ }
7791 else
7792 break;
7793 }
7794 }
7795#endif
7796 } while (0);
7797
7798 if (RT_SUCCESS(rc))
7799 {
7800 /* Update fExtrn. */
7801 pCtx->fExtrn &= ~fWhat;
7802
7803 /* If everything has been imported, clear the HM keeper bit. */
7804 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7805 {
7806 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7807 Assert(!pCtx->fExtrn);
7808 }
7809 }
7810 }
7811 else
7812 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7813
7814 /*
7815 * Restore interrupts.
7816 */
7817 ASMSetFlags(fEFlags);
7818
7819 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7820
7821 if (RT_SUCCESS(rc))
7822 { /* likely */ }
7823 else
7824 return rc;
7825
7826 /*
7827 * Honor any pending CR3 updates.
7828 *
7829 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7830 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7831 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7832 *
7833 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7834 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7835 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7836 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7837 *
7838 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7839 */
7840 if (VMMRZCallRing3IsEnabled(pVCpu))
7841 {
7842 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7843 {
7844 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7845 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7846 }
7847
7848 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7849 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7850
7851 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7852 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7853 }
7854
7855 return VINF_SUCCESS;
7856}
7857
7858
7859/**
7860 * Saves the guest state from the VMCS into the guest-CPU context.
7861 *
7862 * @returns VBox status code.
7863 * @param pVCpu The cross context virtual CPU structure.
7864 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7865 */
7866VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7867{
7868 AssertPtr(pVCpu);
7869 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7870 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7871}
7872
7873
7874/**
7875 * Check per-VM and per-VCPU force flag actions that require us to go back to
7876 * ring-3 for one reason or another.
7877 *
7878 * @returns Strict VBox status code (i.e. informational status codes too)
7879 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7880 * ring-3.
7881 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7882 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7883 * interrupts)
7884 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7885 * all EMTs to be in ring-3.
7886 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7887 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7888 * to the EM loop.
7889 *
7890 * @param pVCpu The cross context virtual CPU structure.
7891 * @param pVmxTransient The VMX-transient structure.
7892 * @param fStepping Whether we are single-stepping the guest using the
7893 * hypervisor debugger.
7894 *
7895 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7896 * is no longer in VMX non-root mode.
7897 */
7898static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
7899{
7900 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7901
7902 /*
7903 * Update pending interrupts into the APIC's IRR.
7904 */
7905 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7906 APICUpdatePendingInterrupts(pVCpu);
7907
7908 /*
7909 * Anything pending? Should be more likely than not if we're doing a good job.
7910 */
7911 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7912 if ( !fStepping
7913 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7914 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7915 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7916 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7917 return VINF_SUCCESS;
7918
7919 /* Pending PGM C3 sync. */
7920 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7921 {
7922 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7923 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7924 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7925 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7926 if (rcStrict != VINF_SUCCESS)
7927 {
7928 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7929 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7930 return rcStrict;
7931 }
7932 }
7933
7934 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7935 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7936 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7937 {
7938 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7939 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7940 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7941 return rc;
7942 }
7943
7944 /* Pending VM request packets, such as hardware interrupts. */
7945 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7946 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7947 {
7948 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7949 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7950 return VINF_EM_PENDING_REQUEST;
7951 }
7952
7953 /* Pending PGM pool flushes. */
7954 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7955 {
7956 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7957 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7958 return VINF_PGM_POOL_FLUSH_PENDING;
7959 }
7960
7961 /* Pending DMA requests. */
7962 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7963 {
7964 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7965 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7966 return VINF_EM_RAW_TO_R3;
7967 }
7968
7969#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7970 /*
7971 * Pending nested-guest events.
7972 *
7973 * Please note the priority of these events are specified and important.
7974 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
7975 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
7976 */
7977 if (pVmxTransient->fIsNestedGuest)
7978 {
7979 /* Pending nested-guest APIC-write. */
7980 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7981 {
7982 Log4Func(("Pending nested-guest APIC-write\n"));
7983 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7984 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7985 return rcStrict;
7986 }
7987
7988 /* Pending nested-guest monitor-trap flag (MTF). */
7989 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
7990 {
7991 Log4Func(("Pending nested-guest MTF\n"));
7992 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
7993 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7994 return rcStrict;
7995 }
7996
7997 /* Pending nested-guest VMX-preemption timer expired. */
7998 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
7999 {
8000 Log4Func(("Pending nested-guest MTF\n"));
8001 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8002 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8003 return rcStrict;
8004 }
8005 }
8006#else
8007 NOREF(pVmxTransient);
8008#endif
8009
8010 return VINF_SUCCESS;
8011}
8012
8013
8014/**
8015 * Converts any TRPM trap into a pending HM event. This is typically used when
8016 * entering from ring-3 (not longjmp returns).
8017 *
8018 * @param pVCpu The cross context virtual CPU structure.
8019 */
8020static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8021{
8022 Assert(TRPMHasTrap(pVCpu));
8023 Assert(!pVCpu->hm.s.Event.fPending);
8024
8025 uint8_t uVector;
8026 TRPMEVENT enmTrpmEvent;
8027 uint32_t uErrCode;
8028 RTGCUINTPTR GCPtrFaultAddress;
8029 uint8_t cbInstr;
8030 bool fIcebp;
8031
8032 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8033 AssertRC(rc);
8034
8035 uint32_t u32IntInfo;
8036 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8037 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8038
8039 rc = TRPMResetTrap(pVCpu);
8040 AssertRC(rc);
8041 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8042 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8043
8044 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8045}
8046
8047
8048/**
8049 * Converts the pending HM event into a TRPM trap.
8050 *
8051 * @param pVCpu The cross context virtual CPU structure.
8052 */
8053static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8054{
8055 Assert(pVCpu->hm.s.Event.fPending);
8056
8057 /* If a trap was already pending, we did something wrong! */
8058 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8059
8060 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8061 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8062 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8063
8064 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8065
8066 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8067 AssertRC(rc);
8068
8069 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8070 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8071
8072 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8073 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8074 else
8075 {
8076 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8077 switch (uVectorType)
8078 {
8079 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8080 TRPMSetTrapDueToIcebp(pVCpu);
8081 RT_FALL_THRU();
8082 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8083 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8084 {
8085 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8086 || ( uVector == X86_XCPT_BP /* INT3 */
8087 || uVector == X86_XCPT_OF /* INTO */
8088 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8089 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8090 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8091 break;
8092 }
8093 }
8094 }
8095
8096 /* We're now done converting the pending event. */
8097 pVCpu->hm.s.Event.fPending = false;
8098}
8099
8100
8101/**
8102 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8103 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8104 *
8105 * @param pVCpu The cross context virtual CPU structure.
8106 * @param pVmcsInfo The VMCS info. object.
8107 */
8108static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8109{
8110 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8111 {
8112 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8113 {
8114 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8115 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8116 AssertRC(rc);
8117 }
8118 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8119}
8120
8121
8122/**
8123 * Clears the interrupt-window exiting control in the VMCS.
8124 *
8125 * @param pVmcsInfo The VMCS info. object.
8126 */
8127DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8128{
8129 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8130 {
8131 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8132 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8133 AssertRC(rc);
8134 }
8135}
8136
8137
8138/**
8139 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8140 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8141 *
8142 * @param pVCpu The cross context virtual CPU structure.
8143 * @param pVmcsInfo The VMCS info. object.
8144 */
8145static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8146{
8147 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8148 {
8149 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8150 {
8151 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8152 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8153 AssertRC(rc);
8154 Log4Func(("Setup NMI-window exiting\n"));
8155 }
8156 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8157}
8158
8159
8160/**
8161 * Clears the NMI-window exiting control in the VMCS.
8162 *
8163 * @param pVmcsInfo The VMCS info. object.
8164 */
8165DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8166{
8167 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8168 {
8169 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8170 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8171 AssertRC(rc);
8172 }
8173}
8174
8175
8176/**
8177 * Does the necessary state syncing before returning to ring-3 for any reason
8178 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8179 *
8180 * @returns VBox status code.
8181 * @param pVCpu The cross context virtual CPU structure.
8182 * @param fImportState Whether to import the guest state from the VMCS back
8183 * to the guest-CPU context.
8184 *
8185 * @remarks No-long-jmp zone!!!
8186 */
8187static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8188{
8189 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8190 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8191
8192 RTCPUID const idCpu = RTMpCpuId();
8193 Log4Func(("HostCpuId=%u\n", idCpu));
8194
8195 /*
8196 * !!! IMPORTANT !!!
8197 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8198 */
8199
8200 /* Save the guest state if necessary. */
8201 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8202 if (fImportState)
8203 {
8204 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8205 AssertRCReturn(rc, rc);
8206 }
8207
8208 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8209 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8210 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8211
8212 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8213#ifdef VBOX_STRICT
8214 if (CPUMIsHyperDebugStateActive(pVCpu))
8215 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8216#endif
8217 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8218 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8219 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8220
8221 /* Restore host-state bits that VT-x only restores partially. */
8222 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8223 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8224 {
8225 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8226 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8227 }
8228 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8229
8230 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8231 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8232 {
8233 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8234 if (!fImportState)
8235 {
8236 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8237 AssertRCReturn(rc, rc);
8238 }
8239 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8240 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8241 }
8242 else
8243 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8244
8245 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8246 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8247
8248 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8249 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8250 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8251 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8252 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8253 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8254 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8255 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8256 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8257 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8258
8259 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8260
8261 /** @todo This partially defeats the purpose of having preemption hooks.
8262 * The problem is, deregistering the hooks should be moved to a place that
8263 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8264 * context.
8265 */
8266 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8267 AssertRCReturn(rc, rc);
8268
8269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8270 /*
8271 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8272 * clear a shadow VMCS before allowing that VMCS to become active on another
8273 * logical processor. We may or may not be importing guest state which clears
8274 * it, so cover for it here.
8275 *
8276 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8277 */
8278 if ( pVmcsInfo->pvShadowVmcs
8279 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8280 {
8281 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8282 AssertRCReturn(rc, rc);
8283 }
8284
8285 /*
8286 * Flag that we need to re-export the host state if we switch to this VMCS before
8287 * executing guest or nested-guest code.
8288 */
8289 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8290#endif
8291
8292 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8293 NOREF(idCpu);
8294 return VINF_SUCCESS;
8295}
8296
8297
8298/**
8299 * Leaves the VT-x session.
8300 *
8301 * @returns VBox status code.
8302 * @param pVCpu The cross context virtual CPU structure.
8303 *
8304 * @remarks No-long-jmp zone!!!
8305 */
8306static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8307{
8308 HM_DISABLE_PREEMPT(pVCpu);
8309 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8310 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8311 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8312
8313 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8314 and done this from the VMXR0ThreadCtxCallback(). */
8315 if (!pVCpu->hm.s.fLeaveDone)
8316 {
8317 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8318 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8319 pVCpu->hm.s.fLeaveDone = true;
8320 }
8321 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8322
8323 /*
8324 * !!! IMPORTANT !!!
8325 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8326 */
8327
8328 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8329 /** @todo Deregistering here means we need to VMCLEAR always
8330 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8331 * for calling VMMR0ThreadCtxHookDisable here! */
8332 VMMR0ThreadCtxHookDisable(pVCpu);
8333
8334 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8335 int rc = HMR0LeaveCpu(pVCpu);
8336 HM_RESTORE_PREEMPT();
8337 return rc;
8338}
8339
8340
8341/**
8342 * Does the necessary state syncing before doing a longjmp to ring-3.
8343 *
8344 * @returns VBox status code.
8345 * @param pVCpu The cross context virtual CPU structure.
8346 *
8347 * @remarks No-long-jmp zone!!!
8348 */
8349DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8350{
8351 return hmR0VmxLeaveSession(pVCpu);
8352}
8353
8354
8355/**
8356 * Take necessary actions before going back to ring-3.
8357 *
8358 * An action requires us to go back to ring-3. This function does the necessary
8359 * steps before we can safely return to ring-3. This is not the same as longjmps
8360 * to ring-3, this is voluntary and prepares the guest so it may continue
8361 * executing outside HM (recompiler/IEM).
8362 *
8363 * @returns VBox status code.
8364 * @param pVCpu The cross context virtual CPU structure.
8365 * @param rcExit The reason for exiting to ring-3. Can be
8366 * VINF_VMM_UNKNOWN_RING3_CALL.
8367 */
8368static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8369{
8370 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8371
8372 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8373 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8374 {
8375 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8376 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8377 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8378 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8379 }
8380
8381 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8382 VMMRZCallRing3Disable(pVCpu);
8383 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8384
8385 /*
8386 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8387 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8388 *
8389 * This is because execution may continue from ring-3 and we would need to inject
8390 * the event from there (hence place it back in TRPM).
8391 */
8392 if (pVCpu->hm.s.Event.fPending)
8393 {
8394 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8395 Assert(!pVCpu->hm.s.Event.fPending);
8396
8397 /* Clear the events from the VMCS. */
8398 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8399 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8400 }
8401#ifdef VBOX_STRICT
8402 /*
8403 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8404 * fatal), we don't care about verifying duplicate injection of events. Errors like
8405 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8406 * function so those should and will be checked below.
8407 */
8408 else if (RT_SUCCESS(rcExit))
8409 {
8410 /*
8411 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8412 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8413 * occasionally, see @bugref{9180#c42}.
8414 *
8415 * However, if the VM-entry failed, any VM entry-interruption info. field would
8416 * be left unmodified as the event would not have been injected to the guest. In
8417 * such cases, don't assert, we're not going to continue guest execution anyway.
8418 */
8419 uint32_t uExitReason;
8420 uint32_t uEntryIntInfo;
8421 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8422 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8423 AssertRC(rc);
8424 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8425 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8426 }
8427#endif
8428
8429 /*
8430 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8431 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8432 * (e.g. TPR below threshold).
8433 */
8434 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8435 {
8436 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8437 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8438 }
8439
8440 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8441 and if we're injecting an event we should have a TRPM trap pending. */
8442 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8443#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8444 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8445#endif
8446
8447 /* Save guest state and restore host state bits. */
8448 int rc = hmR0VmxLeaveSession(pVCpu);
8449 AssertRCReturn(rc, rc);
8450 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8451
8452 /* Thread-context hooks are unregistered at this point!!! */
8453 /* Ring-3 callback notifications are unregistered at this point!!! */
8454
8455 /* Sync recompiler state. */
8456 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8457 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8458 | CPUM_CHANGED_LDTR
8459 | CPUM_CHANGED_GDTR
8460 | CPUM_CHANGED_IDTR
8461 | CPUM_CHANGED_TR
8462 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8463 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8464 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8465 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8466
8467 Assert(!pVCpu->hm.s.fClearTrapFlag);
8468
8469 /* Update the exit-to-ring 3 reason. */
8470 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8471
8472 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8473 if ( rcExit != VINF_EM_RAW_INTERRUPT
8474 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8475 {
8476 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8477 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8478 }
8479
8480 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8481 VMMRZCallRing3Enable(pVCpu);
8482 return rc;
8483}
8484
8485
8486/**
8487 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8488 * longjump to ring-3 and possibly get preempted.
8489 *
8490 * @returns VBox status code.
8491 * @param pVCpu The cross context virtual CPU structure.
8492 * @param enmOperation The operation causing the ring-3 longjump.
8493 */
8494VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8495{
8496 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8497 {
8498 /*
8499 * !!! IMPORTANT !!!
8500 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8501 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8502 */
8503 VMMRZCallRing3RemoveNotification(pVCpu);
8504 VMMRZCallRing3Disable(pVCpu);
8505 HM_DISABLE_PREEMPT(pVCpu);
8506
8507 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8508 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8509 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8510 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8511
8512 /* Restore host-state bits that VT-x only restores partially. */
8513 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8514 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8515 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8516 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8517
8518 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8519 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8520 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8521
8522 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8523 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8524 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8525
8526 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8527 cleared as part of importing the guest state above. */
8528 hmR0VmxClearVmcs(pVmcsInfo);
8529
8530 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8531 VMMR0ThreadCtxHookDisable(pVCpu);
8532
8533 /* Leave HM context. This takes care of local init (term). */
8534 HMR0LeaveCpu(pVCpu);
8535 HM_RESTORE_PREEMPT();
8536 return VINF_SUCCESS;
8537 }
8538
8539 Assert(pVCpu);
8540 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8541 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8542
8543 VMMRZCallRing3Disable(pVCpu);
8544 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8545
8546 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8547
8548 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8549 AssertRCReturn(rc, rc);
8550
8551 VMMRZCallRing3Enable(pVCpu);
8552 return VINF_SUCCESS;
8553}
8554
8555
8556/**
8557 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8558 * stack.
8559 *
8560 * @returns Strict VBox status code (i.e. informational status codes too).
8561 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8562 * @param pVCpu The cross context virtual CPU structure.
8563 * @param uValue The value to push to the guest stack.
8564 */
8565static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8566{
8567 /*
8568 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8569 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8570 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8571 */
8572 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8573 if (pCtx->sp == 1)
8574 return VINF_EM_RESET;
8575 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8576 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8577 AssertRC(rc);
8578 return rc;
8579}
8580
8581
8582/**
8583 * Injects an event into the guest upon VM-entry by updating the relevant fields
8584 * in the VM-entry area in the VMCS.
8585 *
8586 * @returns Strict VBox status code (i.e. informational status codes too).
8587 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8588 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8589 *
8590 * @param pVCpu The cross context virtual CPU structure.
8591 * @param pVmxTransient The VMX-transient structure.
8592 * @param pEvent The event being injected.
8593 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8594 * will be updated if necessary. This cannot not be NULL.
8595 * @param fStepping Whether we're single-stepping guest execution and should
8596 * return VINF_EM_DBG_STEPPED if the event is injected
8597 * directly (registers modified by us, not by hardware on
8598 * VM-entry).
8599 */
8600static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8601 uint32_t *pfIntrState)
8602{
8603 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8604 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8605 Assert(pfIntrState);
8606
8607 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8608 uint32_t u32IntInfo = pEvent->u64IntInfo;
8609 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8610 uint32_t const cbInstr = pEvent->cbInstr;
8611 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8612 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8613 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8614
8615#ifdef VBOX_STRICT
8616 /*
8617 * Validate the error-code-valid bit for hardware exceptions.
8618 * No error codes for exceptions in real-mode.
8619 *
8620 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8621 */
8622 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8623 && !CPUMIsGuestInRealModeEx(pCtx))
8624 {
8625 switch (uVector)
8626 {
8627 case X86_XCPT_PF:
8628 case X86_XCPT_DF:
8629 case X86_XCPT_TS:
8630 case X86_XCPT_NP:
8631 case X86_XCPT_SS:
8632 case X86_XCPT_GP:
8633 case X86_XCPT_AC:
8634 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8635 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8636 RT_FALL_THRU();
8637 default:
8638 break;
8639 }
8640 }
8641
8642 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8643 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8644 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8645#endif
8646
8647 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8648 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8649 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8650 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8651 {
8652 Assert(uVector <= X86_XCPT_LAST);
8653 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8654 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8655 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8656 }
8657 else
8658 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8659
8660 /*
8661 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8662 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8663 * interrupt handler in the (real-mode) guest.
8664 *
8665 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8666 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8667 */
8668 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8669 {
8670 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8671 {
8672 /*
8673 * For CPUs with unrestricted guest execution enabled and with the guest
8674 * in real-mode, we must not set the deliver-error-code bit.
8675 *
8676 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8677 */
8678 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8679 }
8680 else
8681 {
8682 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8683 Assert(PDMVmmDevHeapIsEnabled(pVM));
8684 Assert(pVM->hm.s.vmx.pRealModeTSS);
8685 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8686
8687 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8688 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8689 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8690 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8691 AssertRCReturn(rc2, rc2);
8692
8693 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8694 size_t const cbIdtEntry = sizeof(X86IDTR16);
8695 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8696 {
8697 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8698 if (uVector == X86_XCPT_DF)
8699 return VINF_EM_RESET;
8700
8701 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8702 No error codes for exceptions in real-mode. */
8703 if (uVector == X86_XCPT_GP)
8704 {
8705 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8706 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8707 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8708 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8709 HMEVENT EventXcptDf;
8710 RT_ZERO(EventXcptDf);
8711 EventXcptDf.u64IntInfo = uXcptDfInfo;
8712 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8713 }
8714
8715 /*
8716 * If we're injecting an event with no valid IDT entry, inject a #GP.
8717 * No error codes for exceptions in real-mode.
8718 *
8719 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8720 */
8721 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8722 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8723 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8724 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8725 HMEVENT EventXcptGp;
8726 RT_ZERO(EventXcptGp);
8727 EventXcptGp.u64IntInfo = uXcptGpInfo;
8728 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8729 }
8730
8731 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8732 uint16_t uGuestIp = pCtx->ip;
8733 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8734 {
8735 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8736 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8737 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8738 }
8739 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8740 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8741
8742 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8743 X86IDTR16 IdtEntry;
8744 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8745 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8746 AssertRCReturn(rc2, rc2);
8747
8748 /* Construct the stack frame for the interrupt/exception handler. */
8749 VBOXSTRICTRC rcStrict;
8750 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8751 if (rcStrict == VINF_SUCCESS)
8752 {
8753 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8754 if (rcStrict == VINF_SUCCESS)
8755 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8756 }
8757
8758 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8759 if (rcStrict == VINF_SUCCESS)
8760 {
8761 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8762 pCtx->rip = IdtEntry.offSel;
8763 pCtx->cs.Sel = IdtEntry.uSel;
8764 pCtx->cs.ValidSel = IdtEntry.uSel;
8765 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8766 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8767 && uVector == X86_XCPT_PF)
8768 pCtx->cr2 = GCPtrFault;
8769
8770 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8771 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8772 | HM_CHANGED_GUEST_RSP);
8773
8774 /*
8775 * If we delivered a hardware exception (other than an NMI) and if there was
8776 * block-by-STI in effect, we should clear it.
8777 */
8778 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8779 {
8780 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8781 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8782 Log4Func(("Clearing inhibition due to STI\n"));
8783 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8784 }
8785
8786 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8787 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8788
8789 /*
8790 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8791 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8792 */
8793 pVCpu->hm.s.Event.fPending = false;
8794
8795 /*
8796 * If we eventually support nested-guest execution without unrestricted guest execution,
8797 * we should set fInterceptEvents here.
8798 */
8799 Assert(!pVmxTransient->fIsNestedGuest);
8800
8801 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8802 if (fStepping)
8803 rcStrict = VINF_EM_DBG_STEPPED;
8804 }
8805 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8806 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8807 return rcStrict;
8808 }
8809 }
8810
8811 /*
8812 * Validate.
8813 */
8814 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8815 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8816
8817 /*
8818 * Inject the event into the VMCS.
8819 */
8820 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8821 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8822 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8823 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8824 AssertRC(rc);
8825
8826 /*
8827 * Update guest CR2 if this is a page-fault.
8828 */
8829 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8830 pCtx->cr2 = GCPtrFault;
8831
8832 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8833 return VINF_SUCCESS;
8834}
8835
8836
8837/**
8838 * Evaluates the event to be delivered to the guest and sets it as the pending
8839 * event.
8840 *
8841 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8842 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8843 * NOT restore these force-flags.
8844 *
8845 * @returns Strict VBox status code (i.e. informational status codes too).
8846 * @param pVCpu The cross context virtual CPU structure.
8847 * @param pVmxTransient The VMX-transient structure.
8848 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8849 */
8850static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8851{
8852 Assert(pfIntrState);
8853 Assert(!TRPMHasTrap(pVCpu));
8854
8855 /*
8856 * Compute/update guest-interruptibility state related FFs.
8857 * The FFs will be used below while evaluating events to be injected.
8858 */
8859 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8860
8861 /*
8862 * Evaluate if a new event needs to be injected.
8863 * An event that's already pending has already performed all necessary checks.
8864 */
8865 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8866 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8867 if ( !pVCpu->hm.s.Event.fPending
8868 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8869 {
8870 /** @todo SMI. SMIs take priority over NMIs. */
8871
8872 /*
8873 * NMIs.
8874 * NMIs take priority over external interrupts.
8875 */
8876 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8877 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8878 {
8879 /*
8880 * For a guest, the FF always indicates the guest's ability to receive an NMI.
8881 *
8882 * For a nested-guest, the FF always indicates the outer guest's ability to
8883 * receive an NMI while the guest-interruptibility state bit depends on whether
8884 * the nested-hypervisor is using virtual-NMIs.
8885 */
8886 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
8887 {
8888#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8889 if ( fIsNestedGuest
8890 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
8891 return IEMExecVmxVmexitXcptNmi(pVCpu);
8892#endif
8893 hmR0VmxSetPendingXcptNmi(pVCpu);
8894 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8895 Log4Func(("NMI pending injection\n"));
8896
8897 /* We've injected the NMI, bail. */
8898 return VINF_SUCCESS;
8899 }
8900 else if (!fIsNestedGuest)
8901 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8902 }
8903
8904 /*
8905 * External interrupts (PIC/APIC).
8906 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
8907 * We cannot re-request the interrupt from the controller again.
8908 */
8909 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8910 && !pVCpu->hm.s.fSingleInstruction)
8911 {
8912 Assert(!DBGFIsStepping(pVCpu));
8913 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8914 AssertRC(rc);
8915
8916 if (pCtx->eflags.u32 & X86_EFL_IF)
8917 {
8918#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8919 if ( fIsNestedGuest
8920 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8921 && !CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8922 {
8923 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8924 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8925 return rcStrict;
8926 }
8927#endif
8928 uint8_t u8Interrupt;
8929 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8930 if (RT_SUCCESS(rc))
8931 {
8932#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8933 if ( fIsNestedGuest
8934 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8935 && CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8936 {
8937 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8938 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8939 return rcStrict;
8940 }
8941#endif
8942 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8943 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
8944 }
8945 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8946 {
8947 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8948
8949 if ( !fIsNestedGuest
8950 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8951 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8952 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8953
8954 /*
8955 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8956 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8957 * need to re-set this force-flag here.
8958 */
8959 }
8960 else
8961 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8962
8963 /* We've injected the interrupt or taken necessary action, bail. */
8964 return VINF_SUCCESS;
8965 }
8966 else if (!fIsNestedGuest)
8967 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8968 }
8969 }
8970 else if (!fIsNestedGuest)
8971 {
8972 /*
8973 * An event is being injected or we are in an interrupt shadow. Check if another event is
8974 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
8975 * the pending event.
8976 */
8977 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8978 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8979 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8980 && !pVCpu->hm.s.fSingleInstruction)
8981 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8982 }
8983 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
8984
8985 return VINF_SUCCESS;
8986}
8987
8988
8989/**
8990 * Injects any pending events into the guest if the guest is in a state to
8991 * receive them.
8992 *
8993 * @returns Strict VBox status code (i.e. informational status codes too).
8994 * @param pVCpu The cross context virtual CPU structure.
8995 * @param pVmxTransient The VMX-transient structure.
8996 * @param fIntrState The VT-x guest-interruptibility state.
8997 * @param fStepping Whether we are single-stepping the guest using the
8998 * hypervisor debugger and should return
8999 * VINF_EM_DBG_STEPPED if the event was dispatched
9000 * directly.
9001 */
9002static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9003{
9004 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9005 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9006
9007#ifdef VBOX_STRICT
9008 /*
9009 * Verify guest-interruptibility state.
9010 *
9011 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9012 * since injecting an event may modify the interruptibility state and we must thus always
9013 * use fIntrState.
9014 */
9015 {
9016 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9017 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9018 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9019 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9020 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9021 Assert(!TRPMHasTrap(pVCpu));
9022 NOREF(fBlockMovSS); NOREF(fBlockSti);
9023 }
9024#endif
9025
9026 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9027 if (pVCpu->hm.s.Event.fPending)
9028 {
9029 /*
9030 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9031 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9032 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9033 *
9034 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9035 */
9036 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9037#ifdef VBOX_STRICT
9038 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9039 {
9040 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9041 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9042 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9043 }
9044 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9045 {
9046 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9047 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9048 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9049 }
9050#endif
9051 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9052 uIntType));
9053
9054 /*
9055 * Inject the event and get any changes to the guest-interruptibility state.
9056 *
9057 * The guest-interruptibility state may need to be updated if we inject the event
9058 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9059 */
9060 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9061 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9062
9063 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9064 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9065 else
9066 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9067 }
9068
9069 /*
9070 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9071 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9072 */
9073 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9074 && !pVmxTransient->fIsNestedGuest)
9075 {
9076 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9077
9078 if (!pVCpu->hm.s.fSingleInstruction)
9079 {
9080 /*
9081 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9082 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9083 */
9084 Assert(!DBGFIsStepping(pVCpu));
9085 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9086 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9087 AssertRC(rc);
9088 }
9089 else
9090 {
9091 /*
9092 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9093 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9094 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9095 * we use MTF, so just make sure it's called before executing guest-code.
9096 */
9097 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9098 }
9099 }
9100 /* else: for nested-guest currently handling while merging controls. */
9101
9102 /*
9103 * Finally, update the guest-interruptibility state.
9104 *
9105 * This is required for the real-on-v86 software interrupt injection, for
9106 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9107 */
9108 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9109 AssertRC(rc);
9110
9111 /*
9112 * There's no need to clear the VM-entry interruption-information field here if we're not
9113 * injecting anything. VT-x clears the valid bit on every VM-exit.
9114 *
9115 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9116 */
9117
9118 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9119 return rcStrict;
9120}
9121
9122
9123/**
9124 * Enters the VT-x session.
9125 *
9126 * @returns VBox status code.
9127 * @param pVCpu The cross context virtual CPU structure.
9128 */
9129VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9130{
9131 AssertPtr(pVCpu);
9132 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9133 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9134
9135 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9136 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9137 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9138
9139#ifdef VBOX_STRICT
9140 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9141 RTCCUINTREG uHostCr4 = ASMGetCR4();
9142 if (!(uHostCr4 & X86_CR4_VMXE))
9143 {
9144 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9145 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9146 }
9147#endif
9148
9149 /*
9150 * Load the appropriate VMCS as the current and active one.
9151 */
9152 PVMXVMCSINFO pVmcsInfo;
9153 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9154 if (!fInNestedGuestMode)
9155 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9156 else
9157 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9158 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9159 if (RT_SUCCESS(rc))
9160 {
9161 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9162 pVCpu->hm.s.fLeaveDone = false;
9163 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9164
9165 /*
9166 * Do the EMT scheduled L1D flush here if needed.
9167 */
9168 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9169 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9170 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9171 hmR0MdsClear();
9172 }
9173 return rc;
9174}
9175
9176
9177/**
9178 * The thread-context callback (only on platforms which support it).
9179 *
9180 * @param enmEvent The thread-context event.
9181 * @param pVCpu The cross context virtual CPU structure.
9182 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9183 * @thread EMT(pVCpu)
9184 */
9185VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9186{
9187 AssertPtr(pVCpu);
9188 RT_NOREF1(fGlobalInit);
9189
9190 switch (enmEvent)
9191 {
9192 case RTTHREADCTXEVENT_OUT:
9193 {
9194 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9195 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9196 VMCPU_ASSERT_EMT(pVCpu);
9197
9198 /* No longjmps (logger flushes, locks) in this fragile context. */
9199 VMMRZCallRing3Disable(pVCpu);
9200 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9201
9202 /* Restore host-state (FPU, debug etc.) */
9203 if (!pVCpu->hm.s.fLeaveDone)
9204 {
9205 /*
9206 * Do -not- import the guest-state here as we might already be in the middle of importing
9207 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9208 */
9209 hmR0VmxLeave(pVCpu, false /* fImportState */);
9210 pVCpu->hm.s.fLeaveDone = true;
9211 }
9212
9213 /* Leave HM context, takes care of local init (term). */
9214 int rc = HMR0LeaveCpu(pVCpu);
9215 AssertRC(rc);
9216
9217 /* Restore longjmp state. */
9218 VMMRZCallRing3Enable(pVCpu);
9219 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9220 break;
9221 }
9222
9223 case RTTHREADCTXEVENT_IN:
9224 {
9225 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9226 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9227 VMCPU_ASSERT_EMT(pVCpu);
9228
9229 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9230 VMMRZCallRing3Disable(pVCpu);
9231 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9232
9233 /* Initialize the bare minimum state required for HM. This takes care of
9234 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9235 int rc = hmR0EnterCpu(pVCpu);
9236 AssertRC(rc);
9237 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9238 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9239
9240 /* Load the active VMCS as the current one. */
9241 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9242 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9243 AssertRC(rc);
9244 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9245 pVCpu->hm.s.fLeaveDone = false;
9246
9247 /* Do the EMT scheduled L1D flush if needed. */
9248 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9249 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9250
9251 /* Restore longjmp state. */
9252 VMMRZCallRing3Enable(pVCpu);
9253 break;
9254 }
9255
9256 default:
9257 break;
9258 }
9259}
9260
9261
9262/**
9263 * Exports the host state into the VMCS host-state area.
9264 * Sets up the VM-exit MSR-load area.
9265 *
9266 * The CPU state will be loaded from these fields on every successful VM-exit.
9267 *
9268 * @returns VBox status code.
9269 * @param pVCpu The cross context virtual CPU structure.
9270 *
9271 * @remarks No-long-jump zone!!!
9272 */
9273static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9274{
9275 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9276
9277 int rc = VINF_SUCCESS;
9278 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9279 {
9280 hmR0VmxExportHostControlRegs();
9281
9282 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9283 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9284
9285 hmR0VmxExportHostMsrs(pVCpu);
9286
9287 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9288 }
9289 return rc;
9290}
9291
9292
9293/**
9294 * Saves the host state in the VMCS host-state.
9295 *
9296 * @returns VBox status code.
9297 * @param pVCpu The cross context virtual CPU structure.
9298 *
9299 * @remarks No-long-jump zone!!!
9300 */
9301VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9302{
9303 AssertPtr(pVCpu);
9304 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9305
9306 /*
9307 * Export the host state here while entering HM context.
9308 * When thread-context hooks are used, we might get preempted and have to re-save the host
9309 * state but most of the time we won't be, so do it here before we disable interrupts.
9310 */
9311 return hmR0VmxExportHostState(pVCpu);
9312}
9313
9314
9315/**
9316 * Exports the guest state into the VMCS guest-state area.
9317 *
9318 * The will typically be done before VM-entry when the guest-CPU state and the
9319 * VMCS state may potentially be out of sync.
9320 *
9321 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9322 * VM-entry controls.
9323 * Sets up the appropriate VMX non-root function to execute guest code based on
9324 * the guest CPU mode.
9325 *
9326 * @returns VBox strict status code.
9327 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9328 * without unrestricted guest execution and the VMMDev is not presently
9329 * mapped (e.g. EFI32).
9330 *
9331 * @param pVCpu The cross context virtual CPU structure.
9332 * @param pVmxTransient The VMX-transient structure.
9333 *
9334 * @remarks No-long-jump zone!!!
9335 */
9336static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9337{
9338 AssertPtr(pVCpu);
9339 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9340 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9341
9342 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9343
9344 /*
9345 * Determine real-on-v86 mode.
9346 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9347 */
9348 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9349 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9350 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9351 pVmcsInfo->RealMode.fRealOnV86Active = false;
9352 else
9353 {
9354 Assert(!pVmxTransient->fIsNestedGuest);
9355 pVmcsInfo->RealMode.fRealOnV86Active = true;
9356 }
9357
9358 /*
9359 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9360 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9361 */
9362 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9363 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9364
9365 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9366 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9367
9368 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9369 if (rcStrict == VINF_SUCCESS)
9370 { /* likely */ }
9371 else
9372 {
9373 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9374 return rcStrict;
9375 }
9376
9377 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9378 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9379
9380 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9381 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9382
9383 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9384 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9385 hmR0VmxExportGuestRip(pVCpu);
9386 hmR0VmxExportGuestRsp(pVCpu);
9387 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9388
9389 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9390 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9391
9392 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9393 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9394 | HM_CHANGED_GUEST_CR2
9395 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9396 | HM_CHANGED_GUEST_X87
9397 | HM_CHANGED_GUEST_SSE_AVX
9398 | HM_CHANGED_GUEST_OTHER_XSAVE
9399 | HM_CHANGED_GUEST_XCRx
9400 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9401 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9402 | HM_CHANGED_GUEST_TSC_AUX
9403 | HM_CHANGED_GUEST_OTHER_MSRS
9404 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9405
9406 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9407 return rc;
9408}
9409
9410
9411/**
9412 * Exports the state shared between the host and guest into the VMCS.
9413 *
9414 * @param pVCpu The cross context virtual CPU structure.
9415 * @param pVmxTransient The VMX-transient structure.
9416 *
9417 * @remarks No-long-jump zone!!!
9418 */
9419static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9420{
9421 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9422 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9423
9424 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9425 {
9426 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9427 AssertRC(rc);
9428 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9429
9430 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9431 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9432 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9433 }
9434
9435 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9436 {
9437 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9438 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9439 }
9440
9441 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9442 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9443}
9444
9445
9446/**
9447 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9448 *
9449 * @returns Strict VBox status code (i.e. informational status codes too).
9450 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9451 * without unrestricted guest execution and the VMMDev is not presently
9452 * mapped (e.g. EFI32).
9453 *
9454 * @param pVCpu The cross context virtual CPU structure.
9455 * @param pVmxTransient The VMX-transient structure.
9456 *
9457 * @remarks No-long-jump zone!!!
9458 */
9459static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9460{
9461 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9462 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9463 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9464
9465#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9466 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9467#endif
9468
9469 /*
9470 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9471 * changes. First try to export only these without going through all other changed-flag checks.
9472 */
9473 VBOXSTRICTRC rcStrict;
9474 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9475 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9476 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9477
9478 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9479 if ( (fCtxChanged & fMinimalMask)
9480 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9481 {
9482 hmR0VmxExportGuestRip(pVCpu);
9483 hmR0VmxExportGuestRsp(pVCpu);
9484 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9485 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9486 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9487 }
9488 /* If anything else also changed, go through the full export routine and export as required. */
9489 else if (fCtxChanged & fCtxMask)
9490 {
9491 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9492 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9493 { /* likely */}
9494 else
9495 {
9496 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9497 VBOXSTRICTRC_VAL(rcStrict)));
9498 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9499 return rcStrict;
9500 }
9501 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9502 }
9503 /* Nothing changed, nothing to load here. */
9504 else
9505 rcStrict = VINF_SUCCESS;
9506
9507#ifdef VBOX_STRICT
9508 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9509 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9510 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9511#endif
9512 return rcStrict;
9513}
9514
9515
9516/**
9517 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9518 * and update error record fields accordingly.
9519 *
9520 * @returns VMX_IGS_* error codes.
9521 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9522 * wrong with the guest state.
9523 *
9524 * @param pVCpu The cross context virtual CPU structure.
9525 * @param pVmcsInfo The VMCS info. object.
9526 *
9527 * @remarks This function assumes our cache of the VMCS controls
9528 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9529 */
9530static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9531{
9532#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9533#define HMVMX_CHECK_BREAK(expr, err) do { \
9534 if (!(expr)) { uError = (err); break; } \
9535 } while (0)
9536
9537 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9538 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9539 uint32_t uError = VMX_IGS_ERROR;
9540 uint32_t u32IntrState = 0;
9541 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9542 do
9543 {
9544 int rc;
9545
9546 /*
9547 * Guest-interruptibility state.
9548 *
9549 * Read this first so that any check that fails prior to those that actually
9550 * require the guest-interruptibility state would still reflect the correct
9551 * VMCS value and avoids causing further confusion.
9552 */
9553 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9554 AssertRC(rc);
9555
9556 uint32_t u32Val;
9557 uint64_t u64Val;
9558
9559 /*
9560 * CR0.
9561 */
9562 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9563 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9564 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9565 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9566 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9567 if (fUnrestrictedGuest)
9568 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9569
9570 uint64_t u64GuestCr0;
9571 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9572 AssertRC(rc);
9573 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9574 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9575 if ( !fUnrestrictedGuest
9576 && (u64GuestCr0 & X86_CR0_PG)
9577 && !(u64GuestCr0 & X86_CR0_PE))
9578 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9579
9580 /*
9581 * CR4.
9582 */
9583 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9584 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9585 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9586
9587 uint64_t u64GuestCr4;
9588 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9589 AssertRC(rc);
9590 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9591 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9592
9593 /*
9594 * IA32_DEBUGCTL MSR.
9595 */
9596 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9597 AssertRC(rc);
9598 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9599 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9600 {
9601 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9602 }
9603 uint64_t u64DebugCtlMsr = u64Val;
9604
9605#ifdef VBOX_STRICT
9606 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9607 AssertRC(rc);
9608 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9609#endif
9610 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9611
9612 /*
9613 * RIP and RFLAGS.
9614 */
9615 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9616 AssertRC(rc);
9617 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9618 if ( !fLongModeGuest
9619 || !pCtx->cs.Attr.n.u1Long)
9620 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9621 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9622 * must be identical if the "IA-32e mode guest" VM-entry
9623 * control is 1 and CS.L is 1. No check applies if the
9624 * CPU supports 64 linear-address bits. */
9625
9626 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9627 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9628 AssertRC(rc);
9629 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9630 VMX_IGS_RFLAGS_RESERVED);
9631 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9632 uint32_t const u32Eflags = u64Val;
9633
9634 if ( fLongModeGuest
9635 || ( fUnrestrictedGuest
9636 && !(u64GuestCr0 & X86_CR0_PE)))
9637 {
9638 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9639 }
9640
9641 uint32_t u32EntryInfo;
9642 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9643 AssertRC(rc);
9644 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9645 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9646
9647 /*
9648 * 64-bit checks.
9649 */
9650 if (fLongModeGuest)
9651 {
9652 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9653 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9654 }
9655
9656 if ( !fLongModeGuest
9657 && (u64GuestCr4 & X86_CR4_PCIDE))
9658 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9659
9660 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9661 * 51:32 beyond the processor's physical-address width are 0. */
9662
9663 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9664 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9665 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9666
9667 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9668 AssertRC(rc);
9669 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9670
9671 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9672 AssertRC(rc);
9673 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9674
9675 /*
9676 * PERF_GLOBAL MSR.
9677 */
9678 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9679 {
9680 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9681 AssertRC(rc);
9682 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9683 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9684 }
9685
9686 /*
9687 * PAT MSR.
9688 */
9689 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9690 {
9691 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9692 AssertRC(rc);
9693 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9694 for (unsigned i = 0; i < 8; i++)
9695 {
9696 uint8_t u8Val = (u64Val & 0xff);
9697 if ( u8Val != 0 /* UC */
9698 && u8Val != 1 /* WC */
9699 && u8Val != 4 /* WT */
9700 && u8Val != 5 /* WP */
9701 && u8Val != 6 /* WB */
9702 && u8Val != 7 /* UC- */)
9703 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9704 u64Val >>= 8;
9705 }
9706 }
9707
9708 /*
9709 * EFER MSR.
9710 */
9711 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9712 {
9713 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9714 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9715 AssertRC(rc);
9716 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9717 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9718 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9719 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9720 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9721 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9722 * iemVmxVmentryCheckGuestState(). */
9723 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9724 || !(u64GuestCr0 & X86_CR0_PG)
9725 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9726 VMX_IGS_EFER_LMA_LME_MISMATCH);
9727 }
9728
9729 /*
9730 * Segment registers.
9731 */
9732 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9733 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9734 if (!(u32Eflags & X86_EFL_VM))
9735 {
9736 /* CS */
9737 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9738 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9739 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9740 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9741 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9742 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9743 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9744 /* CS cannot be loaded with NULL in protected mode. */
9745 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9746 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9747 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9748 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9749 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9750 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9751 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9752 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9753 else
9754 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9755
9756 /* SS */
9757 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9758 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9759 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9760 if ( !(pCtx->cr0 & X86_CR0_PE)
9761 || pCtx->cs.Attr.n.u4Type == 3)
9762 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9763
9764 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9765 {
9766 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9767 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9768 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9769 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9770 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9771 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9772 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9773 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9774 }
9775
9776 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9777 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9778 {
9779 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9780 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9781 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9782 || pCtx->ds.Attr.n.u4Type > 11
9783 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9784 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9785 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9786 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9787 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9788 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9789 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9790 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9791 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9792 }
9793 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9794 {
9795 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9796 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9797 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9798 || pCtx->es.Attr.n.u4Type > 11
9799 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9800 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9801 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9802 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9803 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9804 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9805 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9806 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9807 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9808 }
9809 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9810 {
9811 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9812 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9813 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9814 || pCtx->fs.Attr.n.u4Type > 11
9815 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9816 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9817 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9818 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9819 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9820 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9821 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9822 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9823 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9824 }
9825 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9826 {
9827 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9828 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9829 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9830 || pCtx->gs.Attr.n.u4Type > 11
9831 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9832 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9833 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9834 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9835 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9836 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9837 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9838 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9839 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9840 }
9841 /* 64-bit capable CPUs. */
9842 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9843 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9844 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9845 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9846 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9847 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9848 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9849 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9850 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9851 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9852 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9853 }
9854 else
9855 {
9856 /* V86 mode checks. */
9857 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9858 if (pVmcsInfo->RealMode.fRealOnV86Active)
9859 {
9860 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9861 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9862 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9863 }
9864 else
9865 {
9866 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9867 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9868 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9869 }
9870
9871 /* CS */
9872 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9873 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9874 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9875 /* SS */
9876 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9877 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9878 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9879 /* DS */
9880 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9881 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9882 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9883 /* ES */
9884 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9885 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9886 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9887 /* FS */
9888 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9889 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9890 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9891 /* GS */
9892 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9893 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9894 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9895 /* 64-bit capable CPUs. */
9896 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9897 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9898 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9899 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9900 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9901 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9902 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9903 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9904 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9905 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9906 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9907 }
9908
9909 /*
9910 * TR.
9911 */
9912 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9913 /* 64-bit capable CPUs. */
9914 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9915 if (fLongModeGuest)
9916 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9917 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9918 else
9919 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9920 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9921 VMX_IGS_TR_ATTR_TYPE_INVALID);
9922 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9923 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9924 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9925 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9926 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9927 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9928 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9929 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9930
9931 /*
9932 * GDTR and IDTR (64-bit capable checks).
9933 */
9934 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9935 AssertRC(rc);
9936 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9937
9938 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9939 AssertRC(rc);
9940 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9941
9942 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9943 AssertRC(rc);
9944 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9945
9946 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9947 AssertRC(rc);
9948 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9949
9950 /*
9951 * Guest Non-Register State.
9952 */
9953 /* Activity State. */
9954 uint32_t u32ActivityState;
9955 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9956 AssertRC(rc);
9957 HMVMX_CHECK_BREAK( !u32ActivityState
9958 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9959 VMX_IGS_ACTIVITY_STATE_INVALID);
9960 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9961 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9962
9963 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9964 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9965 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9966
9967 /** @todo Activity state and injecting interrupts. Left as a todo since we
9968 * currently don't use activity states but ACTIVE. */
9969
9970 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9971 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9972
9973 /* Guest interruptibility-state. */
9974 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9975 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9976 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9977 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9978 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9979 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9980 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9981 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9982 {
9983 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9984 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9985 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9986 }
9987 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9988 {
9989 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9990 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9991 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9992 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9993 }
9994 /** @todo Assumes the processor is not in SMM. */
9995 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9996 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9997 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9998 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9999 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10000 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10001 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10002 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10003
10004 /* Pending debug exceptions. */
10005 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10006 AssertRC(rc);
10007 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10008 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10009 u32Val = u64Val; /* For pending debug exceptions checks below. */
10010
10011 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10012 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10013 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10014 {
10015 if ( (u32Eflags & X86_EFL_TF)
10016 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10017 {
10018 /* Bit 14 is PendingDebug.BS. */
10019 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10020 }
10021 if ( !(u32Eflags & X86_EFL_TF)
10022 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10023 {
10024 /* Bit 14 is PendingDebug.BS. */
10025 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10026 }
10027 }
10028
10029 /* VMCS link pointer. */
10030 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10031 AssertRC(rc);
10032 if (u64Val != UINT64_C(0xffffffffffffffff))
10033 {
10034 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10035 /** @todo Bits beyond the processor's physical-address width MBZ. */
10036 /** @todo SMM checks. */
10037 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10038 Assert(pVmcsInfo->pvShadowVmcs);
10039 VMXVMCSREVID VmcsRevId;
10040 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10041 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10042 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10043 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10044 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10045 }
10046
10047 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10048 * not using nested paging? */
10049 if ( pVM->hm.s.fNestedPaging
10050 && !fLongModeGuest
10051 && CPUMIsGuestInPAEModeEx(pCtx))
10052 {
10053 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10054 AssertRC(rc);
10055 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10056
10057 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10058 AssertRC(rc);
10059 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10060
10061 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10062 AssertRC(rc);
10063 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10064
10065 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10066 AssertRC(rc);
10067 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10068 }
10069
10070 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10071 if (uError == VMX_IGS_ERROR)
10072 uError = VMX_IGS_REASON_NOT_FOUND;
10073 } while (0);
10074
10075 pVCpu->hm.s.u32HMError = uError;
10076 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10077 return uError;
10078
10079#undef HMVMX_ERROR_BREAK
10080#undef HMVMX_CHECK_BREAK
10081}
10082
10083
10084/**
10085 * Map the APIC-access page for virtualizing APIC accesses.
10086 *
10087 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10088 * this not done as part of exporting guest state, see @bugref{8721}.
10089 *
10090 * @returns VBox status code.
10091 * @param pVCpu The cross context virtual CPU structure.
10092 */
10093static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10094{
10095 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10096 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10097
10098 Assert(PDMHasApic(pVM));
10099 Assert(u64MsrApicBase);
10100
10101 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10102 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10103
10104 /* Unalias the existing mapping. */
10105 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10106 AssertRCReturn(rc, rc);
10107
10108 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10109 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10110 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10111 AssertRCReturn(rc, rc);
10112
10113 /* Update the per-VCPU cache of the APIC base MSR. */
10114 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10115 return VINF_SUCCESS;
10116}
10117
10118
10119/**
10120 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10121 * CPU.
10122 *
10123 * @param idCpu The ID for the CPU the function is called on.
10124 * @param pvUser1 Null, not used.
10125 * @param pvUser2 Null, not used.
10126 */
10127static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10128{
10129 RT_NOREF3(idCpu, pvUser1, pvUser2);
10130 VMXDispatchHostNmi();
10131}
10132
10133
10134/**
10135 * Dispatching an NMI on the host CPU that received it.
10136 *
10137 * @returns VBox status code.
10138 * @param pVCpu The cross context virtual CPU structure.
10139 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10140 * executing when receiving the host NMI in VMX non-root
10141 * operation.
10142 */
10143static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10144{
10145 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10146 Assert(idCpu != NIL_RTCPUID);
10147
10148 /*
10149 * We don't want to delay dispatching the NMI any more than we have to. However,
10150 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10151 * after executing guest or nested-guest code for the following reasons:
10152 *
10153 * - We would need to perform VMREADs with interrupts disabled and is orders of
10154 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10155 * supported by the host hypervisor.
10156 *
10157 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10158 * longer period of time just for handling an edge case like host NMIs which do
10159 * not occur nearly as frequently as other VM-exits.
10160 *
10161 * Let's cover the most likely scenario first. Check if we are on the target CPU
10162 * and dispatch the NMI right away. This should be much faster than calling into
10163 * RTMpOnSpecific() machinery.
10164 */
10165 bool fDispatched = false;
10166 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10167 if (idCpu == RTMpCpuId())
10168 {
10169 VMXDispatchHostNmi();
10170 fDispatched = true;
10171 }
10172 ASMSetFlags(fEFlags);
10173 if (fDispatched)
10174 {
10175 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10176 return VINF_SUCCESS;
10177 }
10178
10179 /*
10180 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10181 * there should be no race or recursion even if we are unlucky enough to be preempted
10182 * (to the target CPU) without dispatching the host NMI above.
10183 */
10184 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10185 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10186}
10187
10188
10189#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10190/**
10191 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10192 * nested-guest using hardware-assisted VMX.
10193 *
10194 * @param pVCpu The cross context virtual CPU structure.
10195 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10196 * @param pVmcsInfoGst The guest VMCS info. object.
10197 */
10198static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10199{
10200 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10201 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10202 Assert(pu64MsrBitmap);
10203
10204 /*
10205 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10206 * MSR that is intercepted by the guest is also intercepted while executing the
10207 * nested-guest using hardware-assisted VMX.
10208 *
10209 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10210 * nested-guest VM-exit even if the outer guest is not intercepting some
10211 * MSRs. We cannot assume the caller has initialized the nested-guest
10212 * MSR bitmap in this case.
10213 *
10214 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10215 * each of its VM-entry, hence initializing it once per-VM while setting
10216 * up the nested-guest VMCS is not sufficient.
10217 */
10218 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10219 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10220 {
10221 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10222 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10223 Assert(pu64MsrBitmapNstGst);
10224 Assert(pu64MsrBitmapGst);
10225
10226 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10227 for (uint32_t i = 0; i < cFrags; i++)
10228 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10229 }
10230 else
10231 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10232}
10233
10234
10235/**
10236 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10237 * hardware-assisted VMX execution of the nested-guest.
10238 *
10239 * For a guest, we don't modify these controls once we set up the VMCS and hence
10240 * this function is never called.
10241 *
10242 * For nested-guests since the nested hypervisor provides these controls on every
10243 * nested-guest VM-entry and could potentially change them everytime we need to
10244 * merge them before every nested-guest VM-entry.
10245 *
10246 * @returns VBox status code.
10247 * @param pVCpu The cross context virtual CPU structure.
10248 */
10249static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10250{
10251 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10252 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10253 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10254 Assert(pVmcsNstGst);
10255
10256 /*
10257 * Merge the controls with the requirements of the guest VMCS.
10258 *
10259 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10260 * VMCS with the features supported by the physical CPU as it's already done by the
10261 * VMLAUNCH/VMRESUME instruction emulation.
10262 *
10263 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10264 * derived from the VMX features supported by the physical CPU.
10265 */
10266
10267 /* Pin-based VM-execution controls. */
10268 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10269
10270 /* Processor-based VM-execution controls. */
10271 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10272 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10273 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10274 | VMX_PROC_CTLS_USE_TPR_SHADOW
10275 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10276
10277 /* Secondary processor-based VM-execution controls. */
10278 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10279 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10280 | VMX_PROC_CTLS2_INVPCID
10281 | VMX_PROC_CTLS2_VMCS_SHADOWING
10282 | VMX_PROC_CTLS2_RDTSCP
10283 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10284 | VMX_PROC_CTLS2_APIC_REG_VIRT
10285 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10286 | VMX_PROC_CTLS2_VMFUNC));
10287
10288 /*
10289 * VM-entry controls:
10290 * These controls contains state that depends on the nested-guest state (primarily
10291 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10292 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10293 * properly continue executing the nested-guest if the EFER MSR changes but does not
10294 * cause a nested-guest VM-exits.
10295 *
10296 * VM-exit controls:
10297 * These controls specify the host state on return. We cannot use the controls from
10298 * the nested hypervisor state as is as it would contain the guest state rather than
10299 * the host state. Since the host state is subject to change (e.g. preemption, trips
10300 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10301 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10302 *
10303 * VM-entry MSR-load:
10304 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10305 * context by the VMLAUNCH/VMRESUME instruction emulation.
10306 *
10307 * VM-exit MSR-store:
10308 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10309 * back into the VM-exit MSR-store area.
10310 *
10311 * VM-exit MSR-load areas:
10312 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10313 * can entirely ignore what the nested hypervisor wants to load here.
10314 */
10315
10316 /*
10317 * Exception bitmap.
10318 *
10319 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10320 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10321 * code more flexible if intercepting exceptions become more dynamic in the future we do
10322 * it as part of exporting the nested-guest state.
10323 */
10324 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10325
10326 /*
10327 * CR0/CR4 guest/host mask.
10328 *
10329 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10330 * cause VM-exits, so we need to merge them here.
10331 */
10332 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10333 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10334
10335 /*
10336 * Page-fault error-code mask and match.
10337 *
10338 * Although we require unrestricted guest execution (and thereby nested-paging) for
10339 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10340 * normally intercept #PFs, it might intercept them for debugging purposes.
10341 *
10342 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10343 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10344 */
10345 uint32_t u32XcptPFMask;
10346 uint32_t u32XcptPFMatch;
10347 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10348 {
10349 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10350 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10351 }
10352 else
10353 {
10354 u32XcptPFMask = 0;
10355 u32XcptPFMatch = 0;
10356 }
10357
10358 /*
10359 * Pause-Loop exiting.
10360 */
10361 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10362 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10363
10364 /*
10365 * Pending debug exceptions.
10366 * Currently just copy whatever the nested-guest provides us.
10367 */
10368 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10369
10370 /*
10371 * I/O Bitmap.
10372 *
10373 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10374 * intercept all I/O port accesses.
10375 */
10376 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10377 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10378
10379 /*
10380 * VMCS shadowing.
10381 *
10382 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10383 * enabled while executing the nested-guest.
10384 */
10385 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10386
10387 /*
10388 * APIC-access page.
10389 */
10390 RTHCPHYS HCPhysApicAccess;
10391 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10392 {
10393 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10394 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10395
10396 /** @todo NSTVMX: This is not really correct but currently is required to make
10397 * things work. We need to re-enable the page handler when we fallback to
10398 * IEM execution of the nested-guest! */
10399 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10400
10401 void *pvPage;
10402 PGMPAGEMAPLOCK PgLockApicAccess;
10403 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10404 if (RT_SUCCESS(rc))
10405 {
10406 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10407 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10408
10409 /** @todo Handle proper releasing of page-mapping lock later. */
10410 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10411 }
10412 else
10413 return rc;
10414 }
10415 else
10416 HCPhysApicAccess = 0;
10417
10418 /*
10419 * Virtual-APIC page and TPR threshold.
10420 */
10421 RTHCPHYS HCPhysVirtApic;
10422 uint32_t u32TprThreshold;
10423 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10424 {
10425 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10426 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10427
10428 void *pvPage;
10429 PGMPAGEMAPLOCK PgLockVirtApic;
10430 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10431 if (RT_SUCCESS(rc))
10432 {
10433 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10434 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10435
10436 /** @todo Handle proper releasing of page-mapping lock later. */
10437 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10438 }
10439 else
10440 return rc;
10441
10442 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10443 }
10444 else
10445 {
10446 HCPhysVirtApic = 0;
10447 u32TprThreshold = 0;
10448
10449 /*
10450 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10451 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10452 * be taken care of by EPT/shadow paging.
10453 */
10454 if (pVM->hm.s.fAllow64BitGuests)
10455 {
10456 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10457 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10458 }
10459 }
10460
10461 /*
10462 * Validate basic assumptions.
10463 */
10464 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10465 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10466 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10467 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10468
10469 /*
10470 * Commit it to the nested-guest VMCS.
10471 */
10472 int rc = VINF_SUCCESS;
10473 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10474 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10475 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10476 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10477 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10478 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10479 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10480 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10481 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10482 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10483 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10484 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10485 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10486 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10487 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10488 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10489 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10490 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10491 {
10492 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10493 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10494 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10495 }
10496 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10497 {
10498 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10499 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10500 }
10501 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10502 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10503 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10504 AssertRC(rc);
10505
10506 /*
10507 * Update the nested-guest VMCS cache.
10508 */
10509 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10510 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10511 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10512 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10513 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10514 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10515 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10516 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10517 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10518
10519 /*
10520 * We need to flush the TLB if we are switching the APIC-access page address.
10521 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10522 */
10523 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10524 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10525
10526 /*
10527 * MSR bitmap.
10528 *
10529 * The MSR bitmap address has already been initialized while setting up the nested-guest
10530 * VMCS, here we need to merge the MSR bitmaps.
10531 */
10532 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10533 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10534
10535 return VINF_SUCCESS;
10536}
10537#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10538
10539
10540/**
10541 * Does the preparations before executing guest code in VT-x.
10542 *
10543 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10544 * recompiler/IEM. We must be cautious what we do here regarding committing
10545 * guest-state information into the VMCS assuming we assuredly execute the
10546 * guest in VT-x mode.
10547 *
10548 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10549 * the common-state (TRPM/forceflags), we must undo those changes so that the
10550 * recompiler/IEM can (and should) use them when it resumes guest execution.
10551 * Otherwise such operations must be done when we can no longer exit to ring-3.
10552 *
10553 * @returns Strict VBox status code (i.e. informational status codes too).
10554 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10555 * have been disabled.
10556 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10557 * pending events).
10558 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10559 * double-fault into the guest.
10560 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10561 * dispatched directly.
10562 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10563 *
10564 * @param pVCpu The cross context virtual CPU structure.
10565 * @param pVmxTransient The VMX-transient structure.
10566 * @param fStepping Whether we are single-stepping the guest in the
10567 * hypervisor debugger. Makes us ignore some of the reasons
10568 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10569 * if event dispatching took place.
10570 */
10571static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10572{
10573 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10574
10575 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10576
10577#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10578 if (pVmxTransient->fIsNestedGuest)
10579 {
10580 RT_NOREF2(pVCpu, fStepping);
10581 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10582 return VINF_EM_RESCHEDULE_REM;
10583 }
10584#endif
10585
10586#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10587 PGMRZDynMapFlushAutoSet(pVCpu);
10588#endif
10589
10590 /*
10591 * Check and process force flag actions, some of which might require us to go back to ring-3.
10592 */
10593 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10594 if (rcStrict == VINF_SUCCESS)
10595 {
10596 /* FFs don't get set all the time. */
10597#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10598 if ( pVmxTransient->fIsNestedGuest
10599 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10600 {
10601 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10602 return VINF_VMX_VMEXIT;
10603 }
10604#endif
10605 }
10606 else
10607 return rcStrict;
10608
10609 /*
10610 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10611 */
10612 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10613 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10614 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10615 && PDMHasApic(pVM))
10616 {
10617 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10618 AssertRCReturn(rc, rc);
10619 }
10620
10621#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10622 /*
10623 * Merge guest VMCS controls with the nested-guest VMCS controls.
10624 *
10625 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10626 * saved state), we should be okay with merging controls as we initialize the
10627 * guest VMCS controls as part of VM setup phase.
10628 */
10629 if ( pVmxTransient->fIsNestedGuest
10630 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10631 {
10632 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10633 AssertRCReturn(rc, rc);
10634 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10635 }
10636#endif
10637
10638 /*
10639 * Evaluate events to be injected into the guest.
10640 *
10641 * Events in TRPM can be injected without inspecting the guest state.
10642 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10643 * guest to cause a VM-exit the next time they are ready to receive the event.
10644 *
10645 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10646 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10647 * subject to interecption. Otherwise, we should have checked and injected them
10648 * manually elsewhere (IEM).
10649 */
10650 if (TRPMHasTrap(pVCpu))
10651 {
10652 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10653 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10654 }
10655
10656 uint32_t fIntrState;
10657 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10658
10659#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10660 /*
10661 * While evaluating pending events if something failed (unlikely) or if we were
10662 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10663 */
10664 if (rcStrict != VINF_SUCCESS)
10665 return rcStrict;
10666 if ( pVmxTransient->fIsNestedGuest
10667 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10668 {
10669 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10670 return VINF_VMX_VMEXIT;
10671 }
10672#else
10673 Assert(rcStrict == VINF_SUCCESS);
10674#endif
10675
10676 /*
10677 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10678 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10679 * also result in triple-faulting the VM.
10680 *
10681 * With nested-guests, the above does not apply since unrestricted guest execution is a
10682 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10683 */
10684 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10685 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10686 { /* likely */ }
10687 else
10688 {
10689 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10690 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10691 return rcStrict;
10692 }
10693
10694 /*
10695 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10696 * import CR3 themselves. We will need to update them here, as even as late as the above
10697 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10698 * the below force flags to be set.
10699 */
10700 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10701 {
10702 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10703 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10704 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10705 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10706 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10707 }
10708 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10709 {
10710 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10711 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10712 }
10713
10714#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10715 /* Paranoia. */
10716 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10717#endif
10718
10719 /*
10720 * No longjmps to ring-3 from this point on!!!
10721 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10722 * This also disables flushing of the R0-logger instance (if any).
10723 */
10724 VMMRZCallRing3Disable(pVCpu);
10725
10726 /*
10727 * Export the guest state bits.
10728 *
10729 * We cannot perform longjmps while loading the guest state because we do not preserve the
10730 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10731 * CPU migration.
10732 *
10733 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10734 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10735 */
10736 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10737 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10738 { /* likely */ }
10739 else
10740 {
10741 VMMRZCallRing3Enable(pVCpu);
10742 return rcStrict;
10743 }
10744
10745 /*
10746 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10747 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10748 * preemption disabled for a while. Since this is purely to aid the
10749 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10750 * disable interrupt on NT.
10751 *
10752 * We need to check for force-flags that could've possible been altered since we last
10753 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10754 * see @bugref{6398}).
10755 *
10756 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10757 * to ring-3 before executing guest code.
10758 */
10759 pVmxTransient->fEFlags = ASMIntDisableFlags();
10760
10761 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10762 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10763 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10764 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10765 {
10766 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10767 {
10768#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10769 /*
10770 * If we are executing a nested-guest make sure that we should intercept subsequent
10771 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10772 * the VM-exit instruction emulation happy.
10773 */
10774 if (pVmxTransient->fIsNestedGuest)
10775 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10776#endif
10777
10778 /*
10779 * We've injected any pending events. This is really the point of no return (to ring-3).
10780 *
10781 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10782 * returns from this function, so do -not- enable them here.
10783 */
10784 pVCpu->hm.s.Event.fPending = false;
10785 return VINF_SUCCESS;
10786 }
10787
10788 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10789 rcStrict = VINF_EM_RAW_INTERRUPT;
10790 }
10791 else
10792 {
10793 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10794 rcStrict = VINF_EM_RAW_TO_R3;
10795 }
10796
10797 ASMSetFlags(pVmxTransient->fEFlags);
10798 VMMRZCallRing3Enable(pVCpu);
10799
10800 return rcStrict;
10801}
10802
10803
10804/**
10805 * Final preparations before executing guest code using hardware-assisted VMX.
10806 *
10807 * We can no longer get preempted to a different host CPU and there are no returns
10808 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10809 * failures), this function is not intended to fail sans unrecoverable hardware
10810 * errors.
10811 *
10812 * @param pVCpu The cross context virtual CPU structure.
10813 * @param pVmxTransient The VMX-transient structure.
10814 *
10815 * @remarks Called with preemption disabled.
10816 * @remarks No-long-jump zone!!!
10817 */
10818static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10819{
10820 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10821 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10822 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10823 Assert(!pVCpu->hm.s.Event.fPending);
10824
10825 /*
10826 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10827 */
10828 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10829 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10830
10831 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10832 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10833 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10834 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10835
10836 if (!CPUMIsGuestFPUStateActive(pVCpu))
10837 {
10838 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10839 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10840 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10841 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10842 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10843 }
10844
10845 /*
10846 * Re-export the host state bits as we may've been preempted (only happens when
10847 * thread-context hooks are used or when the VM start function changes) or if
10848 * the host CR0 is modified while loading the guest FPU state above.
10849 *
10850 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10851 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10852 * see @bugref{8432}.
10853 *
10854 * This may also happen when switching to/from a nested-guest VMCS without leaving
10855 * ring-0.
10856 */
10857 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10858 {
10859 hmR0VmxExportHostState(pVCpu);
10860 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10861 }
10862 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10863
10864 /*
10865 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10866 */
10867 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10868 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10869 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10870
10871 /*
10872 * Store status of the shared guest/host debug state at the time of VM-entry.
10873 */
10874 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10875 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10876
10877 /*
10878 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10879 * more than one conditional check. The post-run side of our code shall determine
10880 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10881 */
10882 if (pVmcsInfo->pbVirtApic)
10883 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10884
10885 /*
10886 * Update the host MSRs values in the VM-exit MSR-load area.
10887 */
10888 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10889 {
10890 if (pVmcsInfo->cExitMsrLoad > 0)
10891 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10892 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10893 }
10894
10895 /*
10896 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10897 * VMX-preemption timer based on the next virtual sync clock deadline.
10898 */
10899 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10900 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10901 {
10902 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10903 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10904 }
10905
10906 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10907 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10908 if (!fIsRdtscIntercepted)
10909 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10910 else
10911 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10912
10913 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10914 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10915 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10916 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10917 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10918 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10919
10920 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10921
10922 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10923 as we're about to start executing the guest. */
10924
10925 /*
10926 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10927 *
10928 * This is done this late as updating the TSC offsetting/preemption timer above
10929 * figures out if we can skip intercepting RDTSCP by calculating the number of
10930 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10931 */
10932 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10933 && !fIsRdtscIntercepted)
10934 {
10935 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10936
10937 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10938 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10939 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10940 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10941 AssertRC(rc);
10942 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10943 pVmxTransient->fRemoveTscAuxMsr = true;
10944 }
10945
10946#ifdef VBOX_STRICT
10947 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10948 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10949 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10950 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10951#endif
10952
10953#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10954 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10955 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10956 * see @bugref{9180#c54}. */
10957 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10958 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10959 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10960#endif
10961}
10962
10963
10964/**
10965 * First C routine invoked after running guest code using hardware-assisted VMX.
10966 *
10967 * @param pVCpu The cross context virtual CPU structure.
10968 * @param pVmxTransient The VMX-transient structure.
10969 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10970 *
10971 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10972 *
10973 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10974 * unconditionally when it is safe to do so.
10975 */
10976static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10977{
10978 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10979
10980 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10981 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10982 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10983 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10984 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10985 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10986
10987 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10988 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10989 {
10990 uint64_t uGstTsc;
10991 if (!pVmxTransient->fIsNestedGuest)
10992 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10993 else
10994 {
10995 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10996 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10997 }
10998 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10999 }
11000
11001 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11002 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
11003 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11004
11005 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11006 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11007#ifdef VBOX_STRICT
11008 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11009#endif
11010 Assert(!ASMIntAreEnabled());
11011 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11012 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11013
11014#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11015 /*
11016 * Clean all the VMCS fields in the transient structure before reading
11017 * anything from the VMCS.
11018 */
11019 pVmxTransient->uExitReason = 0;
11020 pVmxTransient->uExitIntErrorCode = 0;
11021 pVmxTransient->uExitQual = 0;
11022 pVmxTransient->uGuestLinearAddr = 0;
11023 pVmxTransient->uExitIntInfo = 0;
11024 pVmxTransient->cbExitInstr = 0;
11025 pVmxTransient->ExitInstrInfo.u = 0;
11026 pVmxTransient->uEntryIntInfo = 0;
11027 pVmxTransient->uEntryXcptErrorCode = 0;
11028 pVmxTransient->cbEntryInstr = 0;
11029 pVmxTransient->uIdtVectoringInfo = 0;
11030 pVmxTransient->uIdtVectoringErrorCode = 0;
11031#endif
11032
11033 /*
11034 * Save the basic VM-exit reason and check if the VM-entry failed.
11035 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11036 */
11037 uint32_t uExitReason;
11038 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11039 AssertRC(rc);
11040 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11041 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11042
11043 /*
11044 * Log the VM-exit before logging anything else as otherwise it might be a
11045 * tad confusing what happens before and after the world-switch.
11046 */
11047 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11048
11049 /*
11050 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11051 * bitmap permissions, if it was added before VM-entry.
11052 */
11053 if (pVmxTransient->fRemoveTscAuxMsr)
11054 {
11055 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11056 pVmxTransient->fRemoveTscAuxMsr = false;
11057 }
11058
11059 /*
11060 * Check if VMLAUNCH/VMRESUME succeeded.
11061 * If this failed, we cause a guru meditation and cease further execution.
11062 *
11063 * However, if we are executing a nested-guest we might fail if we use the
11064 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11065 */
11066 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11067 {
11068 /*
11069 * Update the VM-exit history array here even if the VM-entry failed due to:
11070 * - Invalid guest state.
11071 * - MSR loading.
11072 * - Machine-check event.
11073 *
11074 * In any of the above cases we will still have a "valid" VM-exit reason
11075 * despite @a fVMEntryFailed being false.
11076 *
11077 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11078 *
11079 * Note! We don't have CS or RIP at this point. Will probably address that later
11080 * by amending the history entry added here.
11081 */
11082 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11083 UINT64_MAX, uHostTsc);
11084
11085 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11086 {
11087 VMMRZCallRing3Enable(pVCpu);
11088
11089 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11090 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11091
11092#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11093 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11094#endif
11095
11096 /*
11097 * Import the guest-interruptibility state always as we need it while evaluating
11098 * injecting events on re-entry.
11099 *
11100 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11101 * checking for real-mode while exporting the state because all bits that cause
11102 * mode changes wrt CR0 are intercepted.
11103 */
11104 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11105#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11106 | HMVMX_CPUMCTX_EXTRN_ALL
11107#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11108 | CPUMCTX_EXTRN_RFLAGS
11109#endif
11110 ;
11111 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11112 AssertRC(rc);
11113
11114 /*
11115 * Sync the TPR shadow with our APIC state.
11116 */
11117 if ( !pVmxTransient->fIsNestedGuest
11118 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11119 {
11120 Assert(pVmcsInfo->pbVirtApic);
11121 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11122 {
11123 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11124 AssertRC(rc);
11125 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11126 }
11127 }
11128
11129 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11130 return;
11131 }
11132 }
11133#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11134 else if (pVmxTransient->fIsNestedGuest)
11135 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11136#endif
11137 else
11138 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11139
11140 VMMRZCallRing3Enable(pVCpu);
11141}
11142
11143
11144/**
11145 * Runs the guest code using hardware-assisted VMX the normal way.
11146 *
11147 * @returns VBox status code.
11148 * @param pVCpu The cross context virtual CPU structure.
11149 * @param pcLoops Pointer to the number of executed loops.
11150 */
11151static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11152{
11153 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11154 Assert(pcLoops);
11155 Assert(*pcLoops <= cMaxResumeLoops);
11156 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11157
11158#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11159 /*
11160 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11161 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11162 * guest VMCS while entering the VMX ring-0 session.
11163 */
11164 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11165 {
11166 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11167 if (RT_SUCCESS(rc))
11168 { /* likely */ }
11169 else
11170 {
11171 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11172 return rc;
11173 }
11174 }
11175#endif
11176
11177 VMXTRANSIENT VmxTransient;
11178 RT_ZERO(VmxTransient);
11179 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11180
11181 /* Paranoia. */
11182 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11183
11184 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11185 for (;;)
11186 {
11187 Assert(!HMR0SuspendPending());
11188 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11189 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11190
11191 /*
11192 * Preparatory work for running nested-guest code, this may force us to
11193 * return to ring-3.
11194 *
11195 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11196 */
11197 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11198 if (rcStrict != VINF_SUCCESS)
11199 break;
11200
11201 /* Interrupts are disabled at this point! */
11202 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11203 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11204 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11205 /* Interrupts are re-enabled at this point! */
11206
11207 /*
11208 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11209 */
11210 if (RT_SUCCESS(rcRun))
11211 { /* very likely */ }
11212 else
11213 {
11214 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11215 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11216 return rcRun;
11217 }
11218
11219 /*
11220 * Profile the VM-exit.
11221 */
11222 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11223 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11224 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11225 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11226 HMVMX_START_EXIT_DISPATCH_PROF();
11227
11228 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11229
11230 /*
11231 * Handle the VM-exit.
11232 */
11233#ifdef HMVMX_USE_FUNCTION_TABLE
11234 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11235#else
11236 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11237#endif
11238 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11239 if (rcStrict == VINF_SUCCESS)
11240 {
11241 if (++(*pcLoops) <= cMaxResumeLoops)
11242 continue;
11243 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11244 rcStrict = VINF_EM_RAW_INTERRUPT;
11245 }
11246 break;
11247 }
11248
11249 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11250 return rcStrict;
11251}
11252
11253
11254#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11255/**
11256 * Runs the nested-guest code using hardware-assisted VMX.
11257 *
11258 * @returns VBox status code.
11259 * @param pVCpu The cross context virtual CPU structure.
11260 * @param pcLoops Pointer to the number of executed loops.
11261 *
11262 * @sa hmR0VmxRunGuestCodeNormal.
11263 */
11264static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11265{
11266 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11267 Assert(pcLoops);
11268 Assert(*pcLoops <= cMaxResumeLoops);
11269 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11270
11271 /*
11272 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11273 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11274 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11275 */
11276 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11277 {
11278 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11279 if (RT_SUCCESS(rc))
11280 { /* likely */ }
11281 else
11282 {
11283 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11284 return rc;
11285 }
11286 }
11287
11288 VMXTRANSIENT VmxTransient;
11289 RT_ZERO(VmxTransient);
11290 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11291 VmxTransient.fIsNestedGuest = true;
11292
11293 /* Paranoia. */
11294 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11295
11296 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11297 for (;;)
11298 {
11299 Assert(!HMR0SuspendPending());
11300 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11301 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11302
11303 /*
11304 * Preparatory work for running guest code, this may force us to
11305 * return to ring-3.
11306 *
11307 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11308 */
11309 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11310 if (rcStrict != VINF_SUCCESS)
11311 break;
11312
11313 /* Interrupts are disabled at this point! */
11314 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11315 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11316 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11317 /* Interrupts are re-enabled at this point! */
11318
11319 /*
11320 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11321 */
11322 if (RT_SUCCESS(rcRun))
11323 { /* very likely */ }
11324 else
11325 {
11326 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11327 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11328 return rcRun;
11329 }
11330
11331 /*
11332 * Profile the VM-exit.
11333 */
11334 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11335 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11336 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11337 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11338 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11339 HMVMX_START_EXIT_DISPATCH_PROF();
11340
11341 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11342
11343 /*
11344 * Handle the VM-exit.
11345 */
11346 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11347 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11348 if (rcStrict == VINF_SUCCESS)
11349 {
11350 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11351 {
11352 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11353 rcStrict = VINF_VMX_VMEXIT;
11354 }
11355 else
11356 {
11357 if (++(*pcLoops) <= cMaxResumeLoops)
11358 continue;
11359 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11360 rcStrict = VINF_EM_RAW_INTERRUPT;
11361 }
11362 }
11363 else
11364 Assert(rcStrict != VINF_VMX_VMEXIT);
11365 break;
11366 }
11367
11368 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11369 return rcStrict;
11370}
11371#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11372
11373
11374/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11375 * probes.
11376 *
11377 * The following few functions and associated structure contains the bloat
11378 * necessary for providing detailed debug events and dtrace probes as well as
11379 * reliable host side single stepping. This works on the principle of
11380 * "subclassing" the normal execution loop and workers. We replace the loop
11381 * method completely and override selected helpers to add necessary adjustments
11382 * to their core operation.
11383 *
11384 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11385 * any performance for debug and analysis features.
11386 *
11387 * @{
11388 */
11389
11390/**
11391 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11392 * the debug run loop.
11393 */
11394typedef struct VMXRUNDBGSTATE
11395{
11396 /** The RIP we started executing at. This is for detecting that we stepped. */
11397 uint64_t uRipStart;
11398 /** The CS we started executing with. */
11399 uint16_t uCsStart;
11400
11401 /** Whether we've actually modified the 1st execution control field. */
11402 bool fModifiedProcCtls : 1;
11403 /** Whether we've actually modified the 2nd execution control field. */
11404 bool fModifiedProcCtls2 : 1;
11405 /** Whether we've actually modified the exception bitmap. */
11406 bool fModifiedXcptBitmap : 1;
11407
11408 /** We desire the modified the CR0 mask to be cleared. */
11409 bool fClearCr0Mask : 1;
11410 /** We desire the modified the CR4 mask to be cleared. */
11411 bool fClearCr4Mask : 1;
11412 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11413 uint32_t fCpe1Extra;
11414 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11415 uint32_t fCpe1Unwanted;
11416 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11417 uint32_t fCpe2Extra;
11418 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11419 uint32_t bmXcptExtra;
11420 /** The sequence number of the Dtrace provider settings the state was
11421 * configured against. */
11422 uint32_t uDtraceSettingsSeqNo;
11423 /** VM-exits to check (one bit per VM-exit). */
11424 uint32_t bmExitsToCheck[3];
11425
11426 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11427 uint32_t fProcCtlsInitial;
11428 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11429 uint32_t fProcCtls2Initial;
11430 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11431 uint32_t bmXcptInitial;
11432} VMXRUNDBGSTATE;
11433AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11434typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11435
11436
11437/**
11438 * Initializes the VMXRUNDBGSTATE structure.
11439 *
11440 * @param pVCpu The cross context virtual CPU structure of the
11441 * calling EMT.
11442 * @param pVmxTransient The VMX-transient structure.
11443 * @param pDbgState The debug state to initialize.
11444 */
11445static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11446{
11447 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11448 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11449
11450 pDbgState->fModifiedProcCtls = false;
11451 pDbgState->fModifiedProcCtls2 = false;
11452 pDbgState->fModifiedXcptBitmap = false;
11453 pDbgState->fClearCr0Mask = false;
11454 pDbgState->fClearCr4Mask = false;
11455 pDbgState->fCpe1Extra = 0;
11456 pDbgState->fCpe1Unwanted = 0;
11457 pDbgState->fCpe2Extra = 0;
11458 pDbgState->bmXcptExtra = 0;
11459 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11460 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11461 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11462}
11463
11464
11465/**
11466 * Updates the VMSC fields with changes requested by @a pDbgState.
11467 *
11468 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11469 * immediately before executing guest code, i.e. when interrupts are disabled.
11470 * We don't check status codes here as we cannot easily assert or return in the
11471 * latter case.
11472 *
11473 * @param pVCpu The cross context virtual CPU structure.
11474 * @param pVmxTransient The VMX-transient structure.
11475 * @param pDbgState The debug state.
11476 */
11477static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11478{
11479 /*
11480 * Ensure desired flags in VMCS control fields are set.
11481 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11482 *
11483 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11484 * there should be no stale data in pCtx at this point.
11485 */
11486 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11487 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11488 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11489 {
11490 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11491 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11492 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11493 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11494 pDbgState->fModifiedProcCtls = true;
11495 }
11496
11497 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11498 {
11499 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11500 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11501 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11502 pDbgState->fModifiedProcCtls2 = true;
11503 }
11504
11505 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11506 {
11507 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11508 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11509 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11510 pDbgState->fModifiedXcptBitmap = true;
11511 }
11512
11513 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11514 {
11515 pVmcsInfo->u64Cr0Mask = 0;
11516 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11517 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11518 }
11519
11520 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11521 {
11522 pVmcsInfo->u64Cr4Mask = 0;
11523 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11524 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11525 }
11526
11527 NOREF(pVCpu);
11528}
11529
11530
11531/**
11532 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11533 * re-entry next time around.
11534 *
11535 * @returns Strict VBox status code (i.e. informational status codes too).
11536 * @param pVCpu The cross context virtual CPU structure.
11537 * @param pVmxTransient The VMX-transient structure.
11538 * @param pDbgState The debug state.
11539 * @param rcStrict The return code from executing the guest using single
11540 * stepping.
11541 */
11542static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11543 VBOXSTRICTRC rcStrict)
11544{
11545 /*
11546 * Restore VM-exit control settings as we may not reenter this function the
11547 * next time around.
11548 */
11549 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11550
11551 /* We reload the initial value, trigger what we can of recalculations the
11552 next time around. From the looks of things, that's all that's required atm. */
11553 if (pDbgState->fModifiedProcCtls)
11554 {
11555 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11556 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11557 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11558 AssertRC(rc2);
11559 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11560 }
11561
11562 /* We're currently the only ones messing with this one, so just restore the
11563 cached value and reload the field. */
11564 if ( pDbgState->fModifiedProcCtls2
11565 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11566 {
11567 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11568 AssertRC(rc2);
11569 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11570 }
11571
11572 /* If we've modified the exception bitmap, we restore it and trigger
11573 reloading and partial recalculation the next time around. */
11574 if (pDbgState->fModifiedXcptBitmap)
11575 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11576
11577 return rcStrict;
11578}
11579
11580
11581/**
11582 * Configures VM-exit controls for current DBGF and DTrace settings.
11583 *
11584 * This updates @a pDbgState and the VMCS execution control fields to reflect
11585 * the necessary VM-exits demanded by DBGF and DTrace.
11586 *
11587 * @param pVCpu The cross context virtual CPU structure.
11588 * @param pVmxTransient The VMX-transient structure. May update
11589 * fUpdatedTscOffsettingAndPreemptTimer.
11590 * @param pDbgState The debug state.
11591 */
11592static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11593{
11594 /*
11595 * Take down the dtrace serial number so we can spot changes.
11596 */
11597 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11598 ASMCompilerBarrier();
11599
11600 /*
11601 * We'll rebuild most of the middle block of data members (holding the
11602 * current settings) as we go along here, so start by clearing it all.
11603 */
11604 pDbgState->bmXcptExtra = 0;
11605 pDbgState->fCpe1Extra = 0;
11606 pDbgState->fCpe1Unwanted = 0;
11607 pDbgState->fCpe2Extra = 0;
11608 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11609 pDbgState->bmExitsToCheck[i] = 0;
11610
11611 /*
11612 * Software interrupts (INT XXh) - no idea how to trigger these...
11613 */
11614 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11615 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11616 || VBOXVMM_INT_SOFTWARE_ENABLED())
11617 {
11618 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11619 }
11620
11621 /*
11622 * INT3 breakpoints - triggered by #BP exceptions.
11623 */
11624 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11625 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11626
11627 /*
11628 * Exception bitmap and XCPT events+probes.
11629 */
11630 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11631 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11632 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11633
11634 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11635 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11636 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11637 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11638 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11639 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11640 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11641 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11642 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11643 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11644 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11645 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11646 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11647 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11648 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11649 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11650 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11651 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11652
11653 if (pDbgState->bmXcptExtra)
11654 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11655
11656 /*
11657 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11658 *
11659 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11660 * So, when adding/changing/removing please don't forget to update it.
11661 *
11662 * Some of the macros are picking up local variables to save horizontal space,
11663 * (being able to see it in a table is the lesser evil here).
11664 */
11665#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11666 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11667 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11668#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11669 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11670 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11671 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11672 } else do { } while (0)
11673#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11674 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11675 { \
11676 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11677 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11678 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11679 } else do { } while (0)
11680#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11681 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11682 { \
11683 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11684 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11685 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11686 } else do { } while (0)
11687#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11688 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11689 { \
11690 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11691 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11692 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11693 } else do { } while (0)
11694
11695 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11696 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11697 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11698 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11699 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11700
11701 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11702 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11703 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11704 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11705 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11706 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11707 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11708 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11709 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11710 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11711 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11712 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11713 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11714 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11715 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11716 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11717 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11718 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11719 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11720 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11721 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11722 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11723 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11724 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11725 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11726 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11727 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11728 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11729 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11730 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11731 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11732 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11733 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11734 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11735 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11736 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11737
11738 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11739 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11740 {
11741 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11742 | CPUMCTX_EXTRN_APIC_TPR);
11743 AssertRC(rc);
11744
11745#if 0 /** @todo fix me */
11746 pDbgState->fClearCr0Mask = true;
11747 pDbgState->fClearCr4Mask = true;
11748#endif
11749 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11750 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11751 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11752 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11753 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11754 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11755 require clearing here and in the loop if we start using it. */
11756 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11757 }
11758 else
11759 {
11760 if (pDbgState->fClearCr0Mask)
11761 {
11762 pDbgState->fClearCr0Mask = false;
11763 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11764 }
11765 if (pDbgState->fClearCr4Mask)
11766 {
11767 pDbgState->fClearCr4Mask = false;
11768 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11769 }
11770 }
11771 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11772 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11773
11774 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11775 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11776 {
11777 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11778 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11779 }
11780 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11781 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11782
11783 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11784 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11785 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11786 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11787 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11788 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11789 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11790 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11791#if 0 /** @todo too slow, fix handler. */
11792 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11793#endif
11794 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11795
11796 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11797 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11798 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11799 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11800 {
11801 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11802 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11803 }
11804 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11805 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11806 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11807 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11808
11809 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11810 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11811 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11812 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11813 {
11814 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11815 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11816 }
11817 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11818 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11819 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11820 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11821
11822 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11823 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11824 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11825 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11826 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11827 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11828 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11829 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11830 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11831 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11832 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11833 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11834 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11835 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11836 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11837 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11838 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11839 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11840 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11841 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11842 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11843 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11844
11845#undef IS_EITHER_ENABLED
11846#undef SET_ONLY_XBM_IF_EITHER_EN
11847#undef SET_CPE1_XBM_IF_EITHER_EN
11848#undef SET_CPEU_XBM_IF_EITHER_EN
11849#undef SET_CPE2_XBM_IF_EITHER_EN
11850
11851 /*
11852 * Sanitize the control stuff.
11853 */
11854 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11855 if (pDbgState->fCpe2Extra)
11856 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11857 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11858 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11859 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11860 {
11861 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11862 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11863 }
11864
11865 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11866 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11867 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11868 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11869}
11870
11871
11872/**
11873 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11874 * appropriate.
11875 *
11876 * The caller has checked the VM-exit against the
11877 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11878 * already, so we don't have to do that either.
11879 *
11880 * @returns Strict VBox status code (i.e. informational status codes too).
11881 * @param pVCpu The cross context virtual CPU structure.
11882 * @param pVmxTransient The VMX-transient structure.
11883 * @param uExitReason The VM-exit reason.
11884 *
11885 * @remarks The name of this function is displayed by dtrace, so keep it short
11886 * and to the point. No longer than 33 chars long, please.
11887 */
11888static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11889{
11890 /*
11891 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11892 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11893 *
11894 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11895 * does. Must add/change/remove both places. Same ordering, please.
11896 *
11897 * Added/removed events must also be reflected in the next section
11898 * where we dispatch dtrace events.
11899 */
11900 bool fDtrace1 = false;
11901 bool fDtrace2 = false;
11902 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11903 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11904 uint32_t uEventArg = 0;
11905#define SET_EXIT(a_EventSubName) \
11906 do { \
11907 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11908 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11909 } while (0)
11910#define SET_BOTH(a_EventSubName) \
11911 do { \
11912 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11913 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11914 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11915 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11916 } while (0)
11917 switch (uExitReason)
11918 {
11919 case VMX_EXIT_MTF:
11920 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11921
11922 case VMX_EXIT_XCPT_OR_NMI:
11923 {
11924 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11925 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11926 {
11927 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11928 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11929 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11930 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11931 {
11932 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11933 {
11934 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11935 uEventArg = pVmxTransient->uExitIntErrorCode;
11936 }
11937 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11938 switch (enmEvent1)
11939 {
11940 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11941 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11942 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11943 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11944 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11945 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11946 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11947 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11948 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11949 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11950 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11951 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11952 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11953 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11954 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11955 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11956 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11957 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11958 default: break;
11959 }
11960 }
11961 else
11962 AssertFailed();
11963 break;
11964
11965 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11966 uEventArg = idxVector;
11967 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11968 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11969 break;
11970 }
11971 break;
11972 }
11973
11974 case VMX_EXIT_TRIPLE_FAULT:
11975 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11976 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11977 break;
11978 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11979 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11980 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11981 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11982 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11983
11984 /* Instruction specific VM-exits: */
11985 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11986 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11987 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11988 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11989 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11990 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11991 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11992 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11993 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11994 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11995 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11996 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11997 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11998 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11999 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12000 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12001 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12002 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12003 case VMX_EXIT_MOV_CRX:
12004 hmR0VmxReadExitQualVmcs(pVmxTransient);
12005 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12006 SET_BOTH(CRX_READ);
12007 else
12008 SET_BOTH(CRX_WRITE);
12009 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12010 break;
12011 case VMX_EXIT_MOV_DRX:
12012 hmR0VmxReadExitQualVmcs(pVmxTransient);
12013 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12014 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12015 SET_BOTH(DRX_READ);
12016 else
12017 SET_BOTH(DRX_WRITE);
12018 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12019 break;
12020 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12021 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12022 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12023 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12024 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12025 case VMX_EXIT_GDTR_IDTR_ACCESS:
12026 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12027 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12028 {
12029 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12030 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12031 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12032 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12033 }
12034 break;
12035
12036 case VMX_EXIT_LDTR_TR_ACCESS:
12037 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12038 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12039 {
12040 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12041 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12042 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12043 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12044 }
12045 break;
12046
12047 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12048 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12049 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12050 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12051 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12052 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12053 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12054 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12055 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12056 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12057 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12058
12059 /* Events that aren't relevant at this point. */
12060 case VMX_EXIT_EXT_INT:
12061 case VMX_EXIT_INT_WINDOW:
12062 case VMX_EXIT_NMI_WINDOW:
12063 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12064 case VMX_EXIT_PREEMPT_TIMER:
12065 case VMX_EXIT_IO_INSTR:
12066 break;
12067
12068 /* Errors and unexpected events. */
12069 case VMX_EXIT_INIT_SIGNAL:
12070 case VMX_EXIT_SIPI:
12071 case VMX_EXIT_IO_SMI:
12072 case VMX_EXIT_SMI:
12073 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12074 case VMX_EXIT_ERR_MSR_LOAD:
12075 case VMX_EXIT_ERR_MACHINE_CHECK:
12076 case VMX_EXIT_PML_FULL:
12077 case VMX_EXIT_VIRTUALIZED_EOI:
12078 break;
12079
12080 default:
12081 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12082 break;
12083 }
12084#undef SET_BOTH
12085#undef SET_EXIT
12086
12087 /*
12088 * Dtrace tracepoints go first. We do them here at once so we don't
12089 * have to copy the guest state saving and stuff a few dozen times.
12090 * Down side is that we've got to repeat the switch, though this time
12091 * we use enmEvent since the probes are a subset of what DBGF does.
12092 */
12093 if (fDtrace1 || fDtrace2)
12094 {
12095 hmR0VmxReadExitQualVmcs(pVmxTransient);
12096 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12097 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12098 switch (enmEvent1)
12099 {
12100 /** @todo consider which extra parameters would be helpful for each probe. */
12101 case DBGFEVENT_END: break;
12102 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12103 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12104 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12105 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12106 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12107 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12108 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12109 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12110 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12111 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12112 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12113 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12114 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12115 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12116 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12117 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12118 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12119 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12120 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12121 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12122 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12123 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12124 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12125 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12126 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12127 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12128 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12129 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12130 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12131 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12132 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12133 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12134 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12135 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12136 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12137 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12138 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12139 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12140 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12141 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12142 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12143 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12144 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12145 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12146 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12147 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12148 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12149 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12150 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12151 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12152 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12153 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12154 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12155 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12156 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12157 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12158 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12159 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12160 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12161 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12162 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12163 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12164 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12165 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12166 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12167 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12168 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12169 }
12170 switch (enmEvent2)
12171 {
12172 /** @todo consider which extra parameters would be helpful for each probe. */
12173 case DBGFEVENT_END: break;
12174 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12175 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12176 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12177 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12178 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12179 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12180 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12181 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12182 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12183 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12184 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12185 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12186 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12187 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12188 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12189 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12190 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12191 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12192 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12193 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12194 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12195 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12196 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12197 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12198 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12199 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12200 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12201 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12202 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12203 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12204 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12205 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12206 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12207 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12208 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12209 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12210 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12211 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12212 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12213 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12214 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12215 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12216 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12217 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12218 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12219 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12220 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12221 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12222 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12223 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12224 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12225 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12226 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12227 }
12228 }
12229
12230 /*
12231 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12232 * the DBGF call will do a full check).
12233 *
12234 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12235 * Note! If we have to events, we prioritize the first, i.e. the instruction
12236 * one, in order to avoid event nesting.
12237 */
12238 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12239 if ( enmEvent1 != DBGFEVENT_END
12240 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12241 {
12242 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12243 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12244 if (rcStrict != VINF_SUCCESS)
12245 return rcStrict;
12246 }
12247 else if ( enmEvent2 != DBGFEVENT_END
12248 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12249 {
12250 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12251 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12252 if (rcStrict != VINF_SUCCESS)
12253 return rcStrict;
12254 }
12255
12256 return VINF_SUCCESS;
12257}
12258
12259
12260/**
12261 * Single-stepping VM-exit filtering.
12262 *
12263 * This is preprocessing the VM-exits and deciding whether we've gotten far
12264 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12265 * handling is performed.
12266 *
12267 * @returns Strict VBox status code (i.e. informational status codes too).
12268 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12269 * @param pVmxTransient The VMX-transient structure.
12270 * @param pDbgState The debug state.
12271 */
12272DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12273{
12274 /*
12275 * Expensive (saves context) generic dtrace VM-exit probe.
12276 */
12277 uint32_t const uExitReason = pVmxTransient->uExitReason;
12278 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12279 { /* more likely */ }
12280 else
12281 {
12282 hmR0VmxReadExitQualVmcs(pVmxTransient);
12283 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12284 AssertRC(rc);
12285 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12286 }
12287
12288 /*
12289 * Check for host NMI, just to get that out of the way.
12290 */
12291 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12292 { /* normally likely */ }
12293 else
12294 {
12295 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12296 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12297 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12298 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12299 }
12300
12301 /*
12302 * Check for single stepping event if we're stepping.
12303 */
12304 if (pVCpu->hm.s.fSingleInstruction)
12305 {
12306 switch (uExitReason)
12307 {
12308 case VMX_EXIT_MTF:
12309 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12310
12311 /* Various events: */
12312 case VMX_EXIT_XCPT_OR_NMI:
12313 case VMX_EXIT_EXT_INT:
12314 case VMX_EXIT_TRIPLE_FAULT:
12315 case VMX_EXIT_INT_WINDOW:
12316 case VMX_EXIT_NMI_WINDOW:
12317 case VMX_EXIT_TASK_SWITCH:
12318 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12319 case VMX_EXIT_APIC_ACCESS:
12320 case VMX_EXIT_EPT_VIOLATION:
12321 case VMX_EXIT_EPT_MISCONFIG:
12322 case VMX_EXIT_PREEMPT_TIMER:
12323
12324 /* Instruction specific VM-exits: */
12325 case VMX_EXIT_CPUID:
12326 case VMX_EXIT_GETSEC:
12327 case VMX_EXIT_HLT:
12328 case VMX_EXIT_INVD:
12329 case VMX_EXIT_INVLPG:
12330 case VMX_EXIT_RDPMC:
12331 case VMX_EXIT_RDTSC:
12332 case VMX_EXIT_RSM:
12333 case VMX_EXIT_VMCALL:
12334 case VMX_EXIT_VMCLEAR:
12335 case VMX_EXIT_VMLAUNCH:
12336 case VMX_EXIT_VMPTRLD:
12337 case VMX_EXIT_VMPTRST:
12338 case VMX_EXIT_VMREAD:
12339 case VMX_EXIT_VMRESUME:
12340 case VMX_EXIT_VMWRITE:
12341 case VMX_EXIT_VMXOFF:
12342 case VMX_EXIT_VMXON:
12343 case VMX_EXIT_MOV_CRX:
12344 case VMX_EXIT_MOV_DRX:
12345 case VMX_EXIT_IO_INSTR:
12346 case VMX_EXIT_RDMSR:
12347 case VMX_EXIT_WRMSR:
12348 case VMX_EXIT_MWAIT:
12349 case VMX_EXIT_MONITOR:
12350 case VMX_EXIT_PAUSE:
12351 case VMX_EXIT_GDTR_IDTR_ACCESS:
12352 case VMX_EXIT_LDTR_TR_ACCESS:
12353 case VMX_EXIT_INVEPT:
12354 case VMX_EXIT_RDTSCP:
12355 case VMX_EXIT_INVVPID:
12356 case VMX_EXIT_WBINVD:
12357 case VMX_EXIT_XSETBV:
12358 case VMX_EXIT_RDRAND:
12359 case VMX_EXIT_INVPCID:
12360 case VMX_EXIT_VMFUNC:
12361 case VMX_EXIT_RDSEED:
12362 case VMX_EXIT_XSAVES:
12363 case VMX_EXIT_XRSTORS:
12364 {
12365 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12366 AssertRCReturn(rc, rc);
12367 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12368 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12369 return VINF_EM_DBG_STEPPED;
12370 break;
12371 }
12372
12373 /* Errors and unexpected events: */
12374 case VMX_EXIT_INIT_SIGNAL:
12375 case VMX_EXIT_SIPI:
12376 case VMX_EXIT_IO_SMI:
12377 case VMX_EXIT_SMI:
12378 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12379 case VMX_EXIT_ERR_MSR_LOAD:
12380 case VMX_EXIT_ERR_MACHINE_CHECK:
12381 case VMX_EXIT_PML_FULL:
12382 case VMX_EXIT_VIRTUALIZED_EOI:
12383 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12384 break;
12385
12386 default:
12387 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12388 break;
12389 }
12390 }
12391
12392 /*
12393 * Check for debugger event breakpoints and dtrace probes.
12394 */
12395 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12396 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12397 {
12398 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12399 if (rcStrict != VINF_SUCCESS)
12400 return rcStrict;
12401 }
12402
12403 /*
12404 * Normal processing.
12405 */
12406#ifdef HMVMX_USE_FUNCTION_TABLE
12407 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12408#else
12409 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12410#endif
12411}
12412
12413
12414/**
12415 * Single steps guest code using hardware-assisted VMX.
12416 *
12417 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12418 * but single-stepping through the hypervisor debugger.
12419 *
12420 * @returns Strict VBox status code (i.e. informational status codes too).
12421 * @param pVCpu The cross context virtual CPU structure.
12422 * @param pcLoops Pointer to the number of executed loops.
12423 *
12424 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12425 */
12426static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12427{
12428 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12429 Assert(pcLoops);
12430 Assert(*pcLoops <= cMaxResumeLoops);
12431
12432 VMXTRANSIENT VmxTransient;
12433 RT_ZERO(VmxTransient);
12434 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12435
12436 /* Set HMCPU indicators. */
12437 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12438 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12439 pVCpu->hm.s.fDebugWantRdTscExit = false;
12440 pVCpu->hm.s.fUsingDebugLoop = true;
12441
12442 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12443 VMXRUNDBGSTATE DbgState;
12444 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12445 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12446
12447 /*
12448 * The loop.
12449 */
12450 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12451 for (;;)
12452 {
12453 Assert(!HMR0SuspendPending());
12454 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12455 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12456 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12457
12458 /* Set up VM-execution controls the next two can respond to. */
12459 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12460
12461 /*
12462 * Preparatory work for running guest code, this may force us to
12463 * return to ring-3.
12464 *
12465 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12466 */
12467 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12468 if (rcStrict != VINF_SUCCESS)
12469 break;
12470
12471 /* Interrupts are disabled at this point! */
12472 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12473
12474 /* Override any obnoxious code in the above two calls. */
12475 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12476
12477 /*
12478 * Finally execute the guest.
12479 */
12480 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12481
12482 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12483 /* Interrupts are re-enabled at this point! */
12484
12485 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12486 if (RT_SUCCESS(rcRun))
12487 { /* very likely */ }
12488 else
12489 {
12490 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12491 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12492 return rcRun;
12493 }
12494
12495 /* Profile the VM-exit. */
12496 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12497 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12498 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12499 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12500 HMVMX_START_EXIT_DISPATCH_PROF();
12501
12502 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12503
12504 /*
12505 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12506 */
12507 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12508 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12509 if (rcStrict != VINF_SUCCESS)
12510 break;
12511 if (++(*pcLoops) > cMaxResumeLoops)
12512 {
12513 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12514 rcStrict = VINF_EM_RAW_INTERRUPT;
12515 break;
12516 }
12517
12518 /*
12519 * Stepping: Did the RIP change, if so, consider it a single step.
12520 * Otherwise, make sure one of the TFs gets set.
12521 */
12522 if (fStepping)
12523 {
12524 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12525 AssertRC(rc);
12526 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12527 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12528 {
12529 rcStrict = VINF_EM_DBG_STEPPED;
12530 break;
12531 }
12532 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12533 }
12534
12535 /*
12536 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12537 */
12538 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12539 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12540 }
12541
12542 /*
12543 * Clear the X86_EFL_TF if necessary.
12544 */
12545 if (pVCpu->hm.s.fClearTrapFlag)
12546 {
12547 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12548 AssertRC(rc);
12549 pVCpu->hm.s.fClearTrapFlag = false;
12550 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12551 }
12552 /** @todo there seems to be issues with the resume flag when the monitor trap
12553 * flag is pending without being used. Seen early in bios init when
12554 * accessing APIC page in protected mode. */
12555
12556 /*
12557 * Restore VM-exit control settings as we may not re-enter this function the
12558 * next time around.
12559 */
12560 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12561
12562 /* Restore HMCPU indicators. */
12563 pVCpu->hm.s.fUsingDebugLoop = false;
12564 pVCpu->hm.s.fDebugWantRdTscExit = false;
12565 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12566
12567 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12568 return rcStrict;
12569}
12570
12571
12572/** @} */
12573
12574
12575/**
12576 * Checks if any expensive dtrace probes are enabled and we should go to the
12577 * debug loop.
12578 *
12579 * @returns true if we should use debug loop, false if not.
12580 */
12581static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12582{
12583 /* It's probably faster to OR the raw 32-bit counter variables together.
12584 Since the variables are in an array and the probes are next to one
12585 another (more or less), we have good locality. So, better read
12586 eight-nine cache lines ever time and only have one conditional, than
12587 128+ conditionals, right? */
12588 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12589 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12590 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12591 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12592 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12593 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12594 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12595 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12596 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12597 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12598 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12599 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12600 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12601 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12602 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12603 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12604 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12605 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12606 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12607 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12608 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12609 ) != 0
12610 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12611 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12612 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12613 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12614 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12615 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12616 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12617 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12618 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12619 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12620 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12621 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12622 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12623 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12624 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12625 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12626 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12627 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12628 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12629 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12630 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12631 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12632 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12633 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12634 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12635 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12636 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12637 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12638 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12639 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12640 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12641 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12642 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12643 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12644 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12645 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12646 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12647 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12648 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12649 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12650 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12651 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12652 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12653 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12654 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12655 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12656 ) != 0
12657 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12658 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12659 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12660 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12661 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12662 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12663 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12664 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12665 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12666 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12667 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12668 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12669 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12670 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12671 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12672 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12673 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12674 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12675 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12676 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12677 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12678 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12679 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12680 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12681 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12682 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12683 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12684 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12685 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12686 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12687 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12688 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12689 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12690 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12691 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12692 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12693 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12694 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12695 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12696 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12697 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12698 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12699 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12700 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12701 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12702 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12703 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12704 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12705 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12706 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12707 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12708 ) != 0;
12709}
12710
12711
12712/**
12713 * Runs the guest using hardware-assisted VMX.
12714 *
12715 * @returns Strict VBox status code (i.e. informational status codes too).
12716 * @param pVCpu The cross context virtual CPU structure.
12717 */
12718VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12719{
12720 AssertPtr(pVCpu);
12721 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12722 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12723 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12724 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12725
12726 VBOXSTRICTRC rcStrict;
12727 uint32_t cLoops = 0;
12728 for (;;)
12729 {
12730#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12731 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12732#else
12733 NOREF(pCtx);
12734 bool const fInNestedGuestMode = false;
12735#endif
12736 if (!fInNestedGuestMode)
12737 {
12738 if ( !pVCpu->hm.s.fUseDebugLoop
12739 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12740 && !DBGFIsStepping(pVCpu)
12741 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12742 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12743 else
12744 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12745 }
12746#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12747 else
12748 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12749
12750 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12751 {
12752 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12753 continue;
12754 }
12755 if (rcStrict == VINF_VMX_VMEXIT)
12756 {
12757 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12758 continue;
12759 }
12760#endif
12761 break;
12762 }
12763
12764 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12765 switch (rcLoop)
12766 {
12767 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12768 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12769 }
12770
12771 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12772 if (RT_FAILURE(rc2))
12773 {
12774 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12775 rcStrict = rc2;
12776 }
12777 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12778 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12779 return rcStrict;
12780}
12781
12782
12783#ifndef HMVMX_USE_FUNCTION_TABLE
12784/**
12785 * Handles a guest VM-exit from hardware-assisted VMX execution.
12786 *
12787 * @returns Strict VBox status code (i.e. informational status codes too).
12788 * @param pVCpu The cross context virtual CPU structure.
12789 * @param pVmxTransient The VMX-transient structure.
12790 */
12791DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12792{
12793#ifdef DEBUG_ramshankar
12794# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12795 do { \
12796 if (a_fSave != 0) \
12797 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12798 VBOXSTRICTRC rcStrict = a_CallExpr; \
12799 if (a_fSave != 0) \
12800 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12801 return rcStrict; \
12802 } while (0)
12803#else
12804# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12805#endif
12806 uint32_t const uExitReason = pVmxTransient->uExitReason;
12807 switch (uExitReason)
12808 {
12809 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12810 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12811 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12812 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12813 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12814 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12815 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12816 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12817 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12818 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12819 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12820 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12821 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12822 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12823 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12824 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12825 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12826 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12827 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12828 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12829 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12830 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12831 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12832 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12833 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12834 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12835 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12836 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12837 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12838 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12839#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12840 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12841 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12842 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12843 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12844 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12845 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12846 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12847 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12848 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12849 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12850 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12851#else
12852 case VMX_EXIT_VMCLEAR:
12853 case VMX_EXIT_VMLAUNCH:
12854 case VMX_EXIT_VMPTRLD:
12855 case VMX_EXIT_VMPTRST:
12856 case VMX_EXIT_VMREAD:
12857 case VMX_EXIT_VMRESUME:
12858 case VMX_EXIT_VMWRITE:
12859 case VMX_EXIT_VMXOFF:
12860 case VMX_EXIT_VMXON:
12861 case VMX_EXIT_INVVPID:
12862 case VMX_EXIT_INVEPT:
12863 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12864#endif
12865
12866 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12867 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12868 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12869
12870 case VMX_EXIT_INIT_SIGNAL:
12871 case VMX_EXIT_SIPI:
12872 case VMX_EXIT_IO_SMI:
12873 case VMX_EXIT_SMI:
12874 case VMX_EXIT_ERR_MSR_LOAD:
12875 case VMX_EXIT_ERR_MACHINE_CHECK:
12876 case VMX_EXIT_PML_FULL:
12877 case VMX_EXIT_VIRTUALIZED_EOI:
12878 case VMX_EXIT_GDTR_IDTR_ACCESS:
12879 case VMX_EXIT_LDTR_TR_ACCESS:
12880 case VMX_EXIT_APIC_WRITE:
12881 case VMX_EXIT_RDRAND:
12882 case VMX_EXIT_RSM:
12883 case VMX_EXIT_VMFUNC:
12884 case VMX_EXIT_ENCLS:
12885 case VMX_EXIT_RDSEED:
12886 case VMX_EXIT_XSAVES:
12887 case VMX_EXIT_XRSTORS:
12888 case VMX_EXIT_UMWAIT:
12889 case VMX_EXIT_TPAUSE:
12890 default:
12891 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12892 }
12893#undef VMEXIT_CALL_RET
12894}
12895#endif /* !HMVMX_USE_FUNCTION_TABLE */
12896
12897
12898#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12899/**
12900 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12901 *
12902 * @returns Strict VBox status code (i.e. informational status codes too).
12903 * @param pVCpu The cross context virtual CPU structure.
12904 * @param pVmxTransient The VMX-transient structure.
12905 */
12906DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12907{
12908 uint32_t const uExitReason = pVmxTransient->uExitReason;
12909 switch (uExitReason)
12910 {
12911 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12912 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12913 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12914 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12915 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12916
12917 /*
12918 * We shouldn't direct host physical interrupts to the nested-guest.
12919 */
12920 case VMX_EXIT_EXT_INT:
12921 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12922
12923 /*
12924 * Instructions that cause VM-exits unconditionally or the condition is
12925 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12926 * happens, it's guaranteed to be a nested-guest VM-exit).
12927 *
12928 * - Provides VM-exit instruction length ONLY.
12929 */
12930 case VMX_EXIT_CPUID: /* Unconditional. */
12931 case VMX_EXIT_VMCALL:
12932 case VMX_EXIT_GETSEC:
12933 case VMX_EXIT_INVD:
12934 case VMX_EXIT_XSETBV:
12935 case VMX_EXIT_VMLAUNCH:
12936 case VMX_EXIT_VMRESUME:
12937 case VMX_EXIT_VMXOFF:
12938 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12939 case VMX_EXIT_VMFUNC:
12940 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12941
12942 /*
12943 * Instructions that cause VM-exits unconditionally or the condition is
12944 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12945 * happens, it's guaranteed to be a nested-guest VM-exit).
12946 *
12947 * - Provides VM-exit instruction length.
12948 * - Provides VM-exit information.
12949 * - Optionally provides Exit qualification.
12950 *
12951 * Since Exit qualification is 0 for all VM-exits where it is not
12952 * applicable, reading and passing it to the guest should produce
12953 * defined behavior.
12954 *
12955 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12956 */
12957 case VMX_EXIT_INVEPT: /* Unconditional. */
12958 case VMX_EXIT_INVVPID:
12959 case VMX_EXIT_VMCLEAR:
12960 case VMX_EXIT_VMPTRLD:
12961 case VMX_EXIT_VMPTRST:
12962 case VMX_EXIT_VMXON:
12963 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12964 case VMX_EXIT_LDTR_TR_ACCESS:
12965 case VMX_EXIT_RDRAND:
12966 case VMX_EXIT_RDSEED:
12967 case VMX_EXIT_XSAVES:
12968 case VMX_EXIT_XRSTORS:
12969 case VMX_EXIT_UMWAIT:
12970 case VMX_EXIT_TPAUSE:
12971 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12972
12973 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12974 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12975 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12976 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12977 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12978 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12979 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12980 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12981 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12982 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12983 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12984 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12985 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12986 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12987 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12988 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12989 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12990 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12991 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12992
12993 case VMX_EXIT_PREEMPT_TIMER:
12994 {
12995 /** @todo NSTVMX: Preempt timer. */
12996 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12997 }
12998
12999 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13000 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13001
13002 case VMX_EXIT_VMREAD:
13003 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13004
13005 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13006 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13007
13008 case VMX_EXIT_INIT_SIGNAL:
13009 case VMX_EXIT_SIPI:
13010 case VMX_EXIT_IO_SMI:
13011 case VMX_EXIT_SMI:
13012 case VMX_EXIT_ERR_MSR_LOAD:
13013 case VMX_EXIT_ERR_MACHINE_CHECK:
13014 case VMX_EXIT_PML_FULL:
13015 case VMX_EXIT_RSM:
13016 default:
13017 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13018 }
13019}
13020#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13021
13022
13023/** @name VM-exit helpers.
13024 * @{
13025 */
13026/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13027/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13028/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13029
13030/** Macro for VM-exits called unexpectedly. */
13031#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13032 do { \
13033 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13034 return VERR_VMX_UNEXPECTED_EXIT; \
13035 } while (0)
13036
13037#ifdef VBOX_STRICT
13038/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13039# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13040 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13041
13042# define HMVMX_ASSERT_PREEMPT_CPUID() \
13043 do { \
13044 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13045 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13046 } while (0)
13047
13048# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13049 do { \
13050 AssertPtr((a_pVCpu)); \
13051 AssertPtr((a_pVmxTransient)); \
13052 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13053 Assert((a_pVmxTransient)->pVmcsInfo); \
13054 Assert(ASMIntAreEnabled()); \
13055 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13056 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13057 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13058 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13059 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13060 HMVMX_ASSERT_PREEMPT_CPUID(); \
13061 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13062 } while (0)
13063
13064# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13065 do { \
13066 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13067 Assert((a_pVmxTransient)->fIsNestedGuest); \
13068 } while (0)
13069
13070# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13071 do { \
13072 Log4Func(("\n")); \
13073 } while (0)
13074#else
13075# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13076 do { \
13077 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13078 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13079 } while (0)
13080
13081# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13082 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13083
13084# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13085#endif
13086
13087#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13088/** Macro that does the necessary privilege checks and intercepted VM-exits for
13089 * guests that attempted to execute a VMX instruction. */
13090# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13091 do \
13092 { \
13093 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13094 if (rcStrictTmp == VINF_SUCCESS) \
13095 { /* likely */ } \
13096 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13097 { \
13098 Assert((a_pVCpu)->hm.s.Event.fPending); \
13099 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13100 return VINF_SUCCESS; \
13101 } \
13102 else \
13103 { \
13104 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13105 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13106 } \
13107 } while (0)
13108
13109/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13110# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13111 do \
13112 { \
13113 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13114 (a_pGCPtrEffAddr)); \
13115 if (rcStrictTmp == VINF_SUCCESS) \
13116 { /* likely */ } \
13117 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13118 { \
13119 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13120 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13121 NOREF(uXcptTmp); \
13122 return VINF_SUCCESS; \
13123 } \
13124 else \
13125 { \
13126 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13127 return rcStrictTmp; \
13128 } \
13129 } while (0)
13130#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13131
13132
13133/**
13134 * Advances the guest RIP by the specified number of bytes.
13135 *
13136 * @param pVCpu The cross context virtual CPU structure.
13137 * @param cbInstr Number of bytes to advance the RIP by.
13138 *
13139 * @remarks No-long-jump zone!!!
13140 */
13141DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13142{
13143 /* Advance the RIP. */
13144 pVCpu->cpum.GstCtx.rip += cbInstr;
13145 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13146
13147 /* Update interrupt inhibition. */
13148 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13149 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13150 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13151}
13152
13153
13154/**
13155 * Advances the guest RIP after reading it from the VMCS.
13156 *
13157 * @returns VBox status code, no informational status codes.
13158 * @param pVCpu The cross context virtual CPU structure.
13159 * @param pVmxTransient The VMX-transient structure.
13160 *
13161 * @remarks No-long-jump zone!!!
13162 */
13163static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13164{
13165 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13166 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13167 AssertRCReturn(rc, rc);
13168
13169 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13170 return VINF_SUCCESS;
13171}
13172
13173
13174/**
13175 * Handle a condition that occurred while delivering an event through the guest or
13176 * nested-guest IDT.
13177 *
13178 * @returns Strict VBox status code (i.e. informational status codes too).
13179 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13180 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13181 * to continue execution of the guest which will delivery the \#DF.
13182 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13183 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13184 *
13185 * @param pVCpu The cross context virtual CPU structure.
13186 * @param pVmxTransient The VMX-transient structure.
13187 *
13188 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13189 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13190 * is due to an EPT violation, PML full or SPP-related event.
13191 *
13192 * @remarks No-long-jump zone!!!
13193 */
13194static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13195{
13196 Assert(!pVCpu->hm.s.Event.fPending);
13197 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13198 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13199 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13200 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13201 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13202
13203 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13204 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13205 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13206 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13207 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13208 {
13209 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13210 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13211
13212 /*
13213 * If the event was a software interrupt (generated with INT n) or a software exception
13214 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13215 * can handle the VM-exit and continue guest execution which will re-execute the
13216 * instruction rather than re-injecting the exception, as that can cause premature
13217 * trips to ring-3 before injection and involve TRPM which currently has no way of
13218 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13219 * the problem).
13220 */
13221 IEMXCPTRAISE enmRaise;
13222 IEMXCPTRAISEINFO fRaiseInfo;
13223 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13224 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13225 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13226 {
13227 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13228 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13229 }
13230 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13231 {
13232 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13233 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13234 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13235
13236 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13237 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13238
13239 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13240
13241 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13242 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13243 {
13244 pVmxTransient->fVectoringPF = true;
13245 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13246 }
13247 }
13248 else
13249 {
13250 /*
13251 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13252 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13253 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13254 */
13255 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13256 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13257 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13258 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13259 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13260 }
13261
13262 /*
13263 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13264 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13265 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13266 * subsequent VM-entry would fail, see @bugref{7445}.
13267 *
13268 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13269 */
13270 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13271 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13272 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13273 && CPUMIsGuestNmiBlocking(pVCpu))
13274 {
13275 CPUMSetGuestNmiBlocking(pVCpu, false);
13276 }
13277
13278 switch (enmRaise)
13279 {
13280 case IEMXCPTRAISE_CURRENT_XCPT:
13281 {
13282 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13283 Assert(rcStrict == VINF_SUCCESS);
13284 break;
13285 }
13286
13287 case IEMXCPTRAISE_PREV_EVENT:
13288 {
13289 uint32_t u32ErrCode;
13290 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13291 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13292 else
13293 u32ErrCode = 0;
13294
13295 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13296 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13297 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13298 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13299
13300 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13301 pVCpu->hm.s.Event.u32ErrCode));
13302 Assert(rcStrict == VINF_SUCCESS);
13303 break;
13304 }
13305
13306 case IEMXCPTRAISE_REEXEC_INSTR:
13307 Assert(rcStrict == VINF_SUCCESS);
13308 break;
13309
13310 case IEMXCPTRAISE_DOUBLE_FAULT:
13311 {
13312 /*
13313 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13314 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13315 */
13316 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13317 {
13318 pVmxTransient->fVectoringDoublePF = true;
13319 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13320 pVCpu->cpum.GstCtx.cr2));
13321 rcStrict = VINF_SUCCESS;
13322 }
13323 else
13324 {
13325 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13326 hmR0VmxSetPendingXcptDF(pVCpu);
13327 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13328 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13329 rcStrict = VINF_HM_DOUBLE_FAULT;
13330 }
13331 break;
13332 }
13333
13334 case IEMXCPTRAISE_TRIPLE_FAULT:
13335 {
13336 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13337 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13338 rcStrict = VINF_EM_RESET;
13339 break;
13340 }
13341
13342 case IEMXCPTRAISE_CPU_HANG:
13343 {
13344 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13345 rcStrict = VERR_EM_GUEST_CPU_HANG;
13346 break;
13347 }
13348
13349 default:
13350 {
13351 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13352 rcStrict = VERR_VMX_IPE_2;
13353 break;
13354 }
13355 }
13356 }
13357 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13358 && !CPUMIsGuestNmiBlocking(pVCpu))
13359 {
13360 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13361 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13362 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13363 {
13364 /*
13365 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13366 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13367 * that virtual NMIs remain blocked until the IRET execution is completed.
13368 *
13369 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13370 */
13371 CPUMSetGuestNmiBlocking(pVCpu, true);
13372 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13373 }
13374 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13375 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13376 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13377 {
13378 /*
13379 * Execution of IRET caused an EPT violation, page-modification log-full event or
13380 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13381 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13382 * that virtual NMIs remain blocked until the IRET execution is completed.
13383 *
13384 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13385 */
13386 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13387 {
13388 CPUMSetGuestNmiBlocking(pVCpu, true);
13389 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13390 }
13391 }
13392 }
13393
13394 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13395 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13396 return rcStrict;
13397}
13398
13399
13400#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13401/**
13402 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13403 * guest attempting to execute a VMX instruction.
13404 *
13405 * @returns Strict VBox status code (i.e. informational status codes too).
13406 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13407 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13408 *
13409 * @param pVCpu The cross context virtual CPU structure.
13410 * @param uExitReason The VM-exit reason.
13411 *
13412 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13413 * @remarks No-long-jump zone!!!
13414 */
13415static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13416{
13417 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13418 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13419
13420 /*
13421 * The physical CPU would have already checked the CPU mode/code segment.
13422 * We shall just assert here for paranoia.
13423 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13424 */
13425 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13426 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13427 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13428
13429 if (uExitReason == VMX_EXIT_VMXON)
13430 {
13431 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13432
13433 /*
13434 * We check CR4.VMXE because it is required to be always set while in VMX operation
13435 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13436 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13437 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13438 */
13439 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13440 {
13441 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13442 hmR0VmxSetPendingXcptUD(pVCpu);
13443 return VINF_HM_PENDING_XCPT;
13444 }
13445 }
13446 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13447 {
13448 /*
13449 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13450 * (other than VMXON), we need to raise a #UD.
13451 */
13452 Log4Func(("Not in VMX root mode -> #UD\n"));
13453 hmR0VmxSetPendingXcptUD(pVCpu);
13454 return VINF_HM_PENDING_XCPT;
13455 }
13456
13457 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13458 return VINF_SUCCESS;
13459}
13460
13461
13462/**
13463 * Decodes the memory operand of an instruction that caused a VM-exit.
13464 *
13465 * The Exit qualification field provides the displacement field for memory
13466 * operand instructions, if any.
13467 *
13468 * @returns Strict VBox status code (i.e. informational status codes too).
13469 * @retval VINF_SUCCESS if the operand was successfully decoded.
13470 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13471 * operand.
13472 * @param pVCpu The cross context virtual CPU structure.
13473 * @param uExitInstrInfo The VM-exit instruction information field.
13474 * @param enmMemAccess The memory operand's access type (read or write).
13475 * @param GCPtrDisp The instruction displacement field, if any. For
13476 * RIP-relative addressing pass RIP + displacement here.
13477 * @param pGCPtrMem Where to store the effective destination memory address.
13478 *
13479 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13480 * virtual-8086 mode hence skips those checks while verifying if the
13481 * segment is valid.
13482 */
13483static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13484 PRTGCPTR pGCPtrMem)
13485{
13486 Assert(pGCPtrMem);
13487 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13488 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13489 | CPUMCTX_EXTRN_CR0);
13490
13491 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13492 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13493 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13494
13495 VMXEXITINSTRINFO ExitInstrInfo;
13496 ExitInstrInfo.u = uExitInstrInfo;
13497 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13498 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13499 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13500 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13501 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13502 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13503 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13504 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13505 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13506
13507 /*
13508 * Validate instruction information.
13509 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13510 */
13511 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13512 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13513 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13514 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13515 AssertLogRelMsgReturn(fIsMemOperand,
13516 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13517
13518 /*
13519 * Compute the complete effective address.
13520 *
13521 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13522 * See AMD spec. 4.5.2 "Segment Registers".
13523 */
13524 RTGCPTR GCPtrMem = GCPtrDisp;
13525 if (fBaseRegValid)
13526 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13527 if (fIdxRegValid)
13528 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13529
13530 RTGCPTR const GCPtrOff = GCPtrMem;
13531 if ( !fIsLongMode
13532 || iSegReg >= X86_SREG_FS)
13533 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13534 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13535
13536 /*
13537 * Validate effective address.
13538 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13539 */
13540 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13541 Assert(cbAccess > 0);
13542 if (fIsLongMode)
13543 {
13544 if (X86_IS_CANONICAL(GCPtrMem))
13545 {
13546 *pGCPtrMem = GCPtrMem;
13547 return VINF_SUCCESS;
13548 }
13549
13550 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13551 * "Data Limit Checks in 64-bit Mode". */
13552 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13553 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13554 return VINF_HM_PENDING_XCPT;
13555 }
13556
13557 /*
13558 * This is a watered down version of iemMemApplySegment().
13559 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13560 * and segment CPL/DPL checks are skipped.
13561 */
13562 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13563 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13564 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13565
13566 /* Check if the segment is present and usable. */
13567 if ( pSel->Attr.n.u1Present
13568 && !pSel->Attr.n.u1Unusable)
13569 {
13570 Assert(pSel->Attr.n.u1DescType);
13571 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13572 {
13573 /* Check permissions for the data segment. */
13574 if ( enmMemAccess == VMXMEMACCESS_WRITE
13575 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13576 {
13577 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13578 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13579 return VINF_HM_PENDING_XCPT;
13580 }
13581
13582 /* Check limits if it's a normal data segment. */
13583 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13584 {
13585 if ( GCPtrFirst32 > pSel->u32Limit
13586 || GCPtrLast32 > pSel->u32Limit)
13587 {
13588 Log4Func(("Data segment limit exceeded. "
13589 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13590 GCPtrLast32, pSel->u32Limit));
13591 if (iSegReg == X86_SREG_SS)
13592 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13593 else
13594 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13595 return VINF_HM_PENDING_XCPT;
13596 }
13597 }
13598 else
13599 {
13600 /* Check limits if it's an expand-down data segment.
13601 Note! The upper boundary is defined by the B bit, not the G bit! */
13602 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13603 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13604 {
13605 Log4Func(("Expand-down data segment limit exceeded. "
13606 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13607 GCPtrLast32, pSel->u32Limit));
13608 if (iSegReg == X86_SREG_SS)
13609 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13610 else
13611 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13612 return VINF_HM_PENDING_XCPT;
13613 }
13614 }
13615 }
13616 else
13617 {
13618 /* Check permissions for the code segment. */
13619 if ( enmMemAccess == VMXMEMACCESS_WRITE
13620 || ( enmMemAccess == VMXMEMACCESS_READ
13621 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13622 {
13623 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13624 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13625 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13626 return VINF_HM_PENDING_XCPT;
13627 }
13628
13629 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13630 if ( GCPtrFirst32 > pSel->u32Limit
13631 || GCPtrLast32 > pSel->u32Limit)
13632 {
13633 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13634 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13635 if (iSegReg == X86_SREG_SS)
13636 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13637 else
13638 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13639 return VINF_HM_PENDING_XCPT;
13640 }
13641 }
13642 }
13643 else
13644 {
13645 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13646 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13647 return VINF_HM_PENDING_XCPT;
13648 }
13649
13650 *pGCPtrMem = GCPtrMem;
13651 return VINF_SUCCESS;
13652}
13653#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13654
13655
13656/**
13657 * VM-exit helper for LMSW.
13658 */
13659static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13660{
13661 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13662 AssertRCReturn(rc, rc);
13663
13664 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13665 AssertMsg( rcStrict == VINF_SUCCESS
13666 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13667
13668 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13669 if (rcStrict == VINF_IEM_RAISED_XCPT)
13670 {
13671 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13672 rcStrict = VINF_SUCCESS;
13673 }
13674
13675 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13676 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13677 return rcStrict;
13678}
13679
13680
13681/**
13682 * VM-exit helper for CLTS.
13683 */
13684static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13685{
13686 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13687 AssertRCReturn(rc, rc);
13688
13689 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13690 AssertMsg( rcStrict == VINF_SUCCESS
13691 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13692
13693 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13694 if (rcStrict == VINF_IEM_RAISED_XCPT)
13695 {
13696 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13697 rcStrict = VINF_SUCCESS;
13698 }
13699
13700 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13701 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13702 return rcStrict;
13703}
13704
13705
13706/**
13707 * VM-exit helper for MOV from CRx (CRx read).
13708 */
13709static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13710{
13711 Assert(iCrReg < 16);
13712 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13713
13714 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13715 AssertRCReturn(rc, rc);
13716
13717 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13718 AssertMsg( rcStrict == VINF_SUCCESS
13719 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13720
13721 if (iGReg == X86_GREG_xSP)
13722 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13723 else
13724 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13725#ifdef VBOX_WITH_STATISTICS
13726 switch (iCrReg)
13727 {
13728 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13729 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13730 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13731 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13732 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13733 }
13734#endif
13735 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13736 return rcStrict;
13737}
13738
13739
13740/**
13741 * VM-exit helper for MOV to CRx (CRx write).
13742 */
13743static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13744{
13745 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13746 AssertRCReturn(rc, rc);
13747
13748 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13749 AssertMsg( rcStrict == VINF_SUCCESS
13750 || rcStrict == VINF_IEM_RAISED_XCPT
13751 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13752
13753 switch (iCrReg)
13754 {
13755 case 0:
13756 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13757 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13758 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13759 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13760 break;
13761
13762 case 2:
13763 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13764 /* Nothing to do here, CR2 it's not part of the VMCS. */
13765 break;
13766
13767 case 3:
13768 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13769 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13770 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13771 break;
13772
13773 case 4:
13774 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13775 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13776 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13777 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13778 break;
13779
13780 case 8:
13781 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13782 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13783 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13784 break;
13785
13786 default:
13787 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13788 break;
13789 }
13790
13791 if (rcStrict == VINF_IEM_RAISED_XCPT)
13792 {
13793 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13794 rcStrict = VINF_SUCCESS;
13795 }
13796 return rcStrict;
13797}
13798
13799
13800/**
13801 * VM-exit exception handler for \#PF (Page-fault exception).
13802 *
13803 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13804 */
13805static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13806{
13807 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13808 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13809 hmR0VmxReadExitQualVmcs(pVmxTransient);
13810
13811 if (!pVM->hm.s.fNestedPaging)
13812 { /* likely */ }
13813 else
13814 {
13815#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13816 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13817#endif
13818 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13819 if (!pVmxTransient->fVectoringDoublePF)
13820 {
13821 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13822 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13823 }
13824 else
13825 {
13826 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13827 Assert(!pVmxTransient->fIsNestedGuest);
13828 hmR0VmxSetPendingXcptDF(pVCpu);
13829 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13830 }
13831 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13832 return VINF_SUCCESS;
13833 }
13834
13835 Assert(!pVmxTransient->fIsNestedGuest);
13836
13837 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13838 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13839 if (pVmxTransient->fVectoringPF)
13840 {
13841 Assert(pVCpu->hm.s.Event.fPending);
13842 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13843 }
13844
13845 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13846 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13847 AssertRCReturn(rc, rc);
13848
13849 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13850 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13851
13852 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13853 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13854
13855 Log4Func(("#PF: rc=%Rrc\n", rc));
13856 if (rc == VINF_SUCCESS)
13857 {
13858 /*
13859 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13860 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13861 */
13862 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13863 TRPMResetTrap(pVCpu);
13864 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13865 return rc;
13866 }
13867
13868 if (rc == VINF_EM_RAW_GUEST_TRAP)
13869 {
13870 if (!pVmxTransient->fVectoringDoublePF)
13871 {
13872 /* It's a guest page fault and needs to be reflected to the guest. */
13873 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13874 TRPMResetTrap(pVCpu);
13875 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13876 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13877 uGstErrorCode, pVmxTransient->uExitQual);
13878 }
13879 else
13880 {
13881 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13882 TRPMResetTrap(pVCpu);
13883 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13884 hmR0VmxSetPendingXcptDF(pVCpu);
13885 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13886 }
13887
13888 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13889 return VINF_SUCCESS;
13890 }
13891
13892 TRPMResetTrap(pVCpu);
13893 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13894 return rc;
13895}
13896
13897
13898/**
13899 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13900 *
13901 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13902 */
13903static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13904{
13905 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13906 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13907
13908 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13909 AssertRCReturn(rc, rc);
13910
13911 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13912 {
13913 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13914 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13915
13916 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13917 * provides VM-exit instruction length. If this causes problem later,
13918 * disassemble the instruction like it's done on AMD-V. */
13919 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13920 AssertRCReturn(rc2, rc2);
13921 return rc;
13922 }
13923
13924 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13925 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13926 return VINF_SUCCESS;
13927}
13928
13929
13930/**
13931 * VM-exit exception handler for \#BP (Breakpoint exception).
13932 *
13933 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13934 */
13935static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13936{
13937 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13938 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13939
13940 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13941 AssertRCReturn(rc, rc);
13942
13943 if (!pVmxTransient->fIsNestedGuest)
13944 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13945 else
13946 rc = VINF_EM_RAW_GUEST_TRAP;
13947
13948 if (rc == VINF_EM_RAW_GUEST_TRAP)
13949 {
13950 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13951 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13952 rc = VINF_SUCCESS;
13953 }
13954
13955 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13956 return rc;
13957}
13958
13959
13960/**
13961 * VM-exit exception handler for \#AC (Alignment-check exception).
13962 *
13963 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13964 */
13965static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13966{
13967 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13968 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13969
13970 /* Re-inject it. We'll detect any nesting before getting here. */
13971 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13972 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13973 return VINF_SUCCESS;
13974}
13975
13976
13977/**
13978 * VM-exit exception handler for \#DB (Debug exception).
13979 *
13980 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13981 */
13982static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13983{
13984 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13985 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13986
13987 /*
13988 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13989 */
13990 hmR0VmxReadExitQualVmcs(pVmxTransient);
13991
13992 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13993 uint64_t const uDR6 = X86_DR6_INIT_VAL
13994 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13995 | X86_DR6_BD | X86_DR6_BS));
13996
13997 int rc;
13998 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13999 if (!pVmxTransient->fIsNestedGuest)
14000 {
14001 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14002
14003 /*
14004 * Prevents stepping twice over the same instruction when the guest is stepping using
14005 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14006 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14007 */
14008 if ( rc == VINF_EM_DBG_STEPPED
14009 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14010 {
14011 Assert(pVCpu->hm.s.fSingleInstruction);
14012 rc = VINF_EM_RAW_GUEST_TRAP;
14013 }
14014 }
14015 else
14016 rc = VINF_EM_RAW_GUEST_TRAP;
14017 Log6Func(("rc=%Rrc\n", rc));
14018 if (rc == VINF_EM_RAW_GUEST_TRAP)
14019 {
14020 /*
14021 * The exception was for the guest. Update DR6, DR7.GD and
14022 * IA32_DEBUGCTL.LBR before forwarding it.
14023 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14024 */
14025 VMMRZCallRing3Disable(pVCpu);
14026 HM_DISABLE_PREEMPT(pVCpu);
14027
14028 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14029 pCtx->dr[6] |= uDR6;
14030 if (CPUMIsGuestDebugStateActive(pVCpu))
14031 ASMSetDR6(pCtx->dr[6]);
14032
14033 HM_RESTORE_PREEMPT();
14034 VMMRZCallRing3Enable(pVCpu);
14035
14036 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14037 AssertRCReturn(rc, rc);
14038
14039 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14040 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14041
14042 /* Paranoia. */
14043 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14044 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14045
14046 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14047 AssertRC(rc);
14048
14049 /*
14050 * Raise #DB in the guest.
14051 *
14052 * It is important to reflect exactly what the VM-exit gave us (preserving the
14053 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14054 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14055 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14056 *
14057 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14058 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14059 */
14060 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14061 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14062 return VINF_SUCCESS;
14063 }
14064
14065 /*
14066 * Not a guest trap, must be a hypervisor related debug event then.
14067 * Update DR6 in case someone is interested in it.
14068 */
14069 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14070 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14071 CPUMSetHyperDR6(pVCpu, uDR6);
14072
14073 return rc;
14074}
14075
14076
14077/**
14078 * Hacks its way around the lovely mesa driver's backdoor accesses.
14079 *
14080 * @sa hmR0SvmHandleMesaDrvGp.
14081 */
14082static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14083{
14084 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14085 RT_NOREF(pCtx);
14086
14087 /* For now we'll just skip the instruction. */
14088 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14089}
14090
14091
14092/**
14093 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14094 * backdoor logging w/o checking what it is running inside.
14095 *
14096 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14097 * backdoor port and magic numbers loaded in registers.
14098 *
14099 * @returns true if it is, false if it isn't.
14100 * @sa hmR0SvmIsMesaDrvGp.
14101 */
14102DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14103{
14104 /* 0xed: IN eAX,dx */
14105 uint8_t abInstr[1];
14106 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14107 return false;
14108
14109 /* Check that it is #GP(0). */
14110 if (pVmxTransient->uExitIntErrorCode != 0)
14111 return false;
14112
14113 /* Check magic and port. */
14114 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14115 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14116 if (pCtx->rax != UINT32_C(0x564d5868))
14117 return false;
14118 if (pCtx->dx != UINT32_C(0x5658))
14119 return false;
14120
14121 /* Flat ring-3 CS. */
14122 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14123 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14124 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14125 if (pCtx->cs.Attr.n.u2Dpl != 3)
14126 return false;
14127 if (pCtx->cs.u64Base != 0)
14128 return false;
14129
14130 /* Check opcode. */
14131 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14132 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14133 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14134 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14135 if (RT_FAILURE(rc))
14136 return false;
14137 if (abInstr[0] != 0xed)
14138 return false;
14139
14140 return true;
14141}
14142
14143
14144/**
14145 * VM-exit exception handler for \#GP (General-protection exception).
14146 *
14147 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14148 */
14149static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14150{
14151 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14152 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14153
14154 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14155 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14156 if (pVmcsInfo->RealMode.fRealOnV86Active)
14157 { /* likely */ }
14158 else
14159 {
14160#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14161 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14162#endif
14163 /*
14164 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14165 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14166 */
14167 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14168 AssertRCReturn(rc, rc);
14169 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14170 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14171
14172 if ( pVmxTransient->fIsNestedGuest
14173 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14174 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14175 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14176 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14177 else
14178 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14179 return rc;
14180 }
14181
14182 Assert(CPUMIsGuestInRealModeEx(pCtx));
14183 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14184 Assert(!pVmxTransient->fIsNestedGuest);
14185
14186 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14187 AssertRCReturn(rc, rc);
14188
14189 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14190 if (rcStrict == VINF_SUCCESS)
14191 {
14192 if (!CPUMIsGuestInRealModeEx(pCtx))
14193 {
14194 /*
14195 * The guest is no longer in real-mode, check if we can continue executing the
14196 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14197 */
14198 pVmcsInfo->RealMode.fRealOnV86Active = false;
14199 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14200 {
14201 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14202 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14203 }
14204 else
14205 {
14206 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14207 rcStrict = VINF_EM_RESCHEDULE;
14208 }
14209 }
14210 else
14211 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14212 }
14213 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14214 {
14215 rcStrict = VINF_SUCCESS;
14216 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14217 }
14218 return VBOXSTRICTRC_VAL(rcStrict);
14219}
14220
14221
14222/**
14223 * VM-exit exception handler wrapper for all other exceptions that are not handled
14224 * by a specific handler.
14225 *
14226 * This simply re-injects the exception back into the VM without any special
14227 * processing.
14228 *
14229 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14230 */
14231static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14232{
14233 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14234
14235#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14236 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14237 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14238 ("uVector=%#x u32XcptBitmap=%#X32\n",
14239 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14240 NOREF(pVmcsInfo);
14241#endif
14242
14243 /*
14244 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14245 * would have been handled while checking exits due to event delivery.
14246 */
14247 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14248
14249#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14250 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14251 AssertRCReturn(rc, rc);
14252 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14253#endif
14254
14255#ifdef VBOX_WITH_STATISTICS
14256 switch (uVector)
14257 {
14258 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14259 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14260 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14261 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14262 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14263 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14264 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14265 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14266 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14267 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14268 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14269 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14270 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14271 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14272 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14273 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14274 default:
14275 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14276 break;
14277 }
14278#endif
14279
14280 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14281 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14282 NOREF(uVector);
14283
14284 /* Re-inject the original exception into the guest. */
14285 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14286 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14287 return VINF_SUCCESS;
14288}
14289
14290
14291/**
14292 * VM-exit exception handler for all exceptions (except NMIs!).
14293 *
14294 * @remarks This may be called for both guests and nested-guests. Take care to not
14295 * make assumptions and avoid doing anything that is not relevant when
14296 * executing a nested-guest (e.g., Mesa driver hacks).
14297 */
14298static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14299{
14300 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14301
14302 /*
14303 * If this VM-exit occurred while delivering an event through the guest IDT, take
14304 * action based on the return code and additional hints (e.g. for page-faults)
14305 * that will be updated in the VMX transient structure.
14306 */
14307 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14308 if (rcStrict == VINF_SUCCESS)
14309 {
14310 /*
14311 * If an exception caused a VM-exit due to delivery of an event, the original
14312 * event may have to be re-injected into the guest. We shall reinject it and
14313 * continue guest execution. However, page-fault is a complicated case and
14314 * needs additional processing done in hmR0VmxExitXcptPF().
14315 */
14316 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14317 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14318 if ( !pVCpu->hm.s.Event.fPending
14319 || uVector == X86_XCPT_PF)
14320 {
14321 switch (uVector)
14322 {
14323 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14324 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14325 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14326 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14327 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14328 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14329 default:
14330 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14331 }
14332 }
14333 /* else: inject pending event before resuming guest execution. */
14334 }
14335 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14336 {
14337 Assert(pVCpu->hm.s.Event.fPending);
14338 rcStrict = VINF_SUCCESS;
14339 }
14340
14341 return rcStrict;
14342}
14343/** @} */
14344
14345
14346/** @name VM-exit handlers.
14347 * @{
14348 */
14349/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14350/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14351/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14352
14353/**
14354 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14355 */
14356HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14357{
14358 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14359 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14360 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14361 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14362 return VINF_SUCCESS;
14363 return VINF_EM_RAW_INTERRUPT;
14364}
14365
14366
14367/**
14368 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14369 * VM-exit.
14370 */
14371HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14372{
14373 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14374 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14375
14376 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14377
14378 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14379 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14380 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14381
14382 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14383 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14384 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14385 NOREF(pVmcsInfo);
14386
14387 VBOXSTRICTRC rcStrict;
14388 switch (uExitIntType)
14389 {
14390 /*
14391 * Host physical NMIs:
14392 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14393 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14394 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14395 *
14396 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14397 * See Intel spec. 27.5.5 "Updating Non-Register State".
14398 */
14399 case VMX_EXIT_INT_INFO_TYPE_NMI:
14400 {
14401 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14402 break;
14403 }
14404
14405 /*
14406 * Privileged software exceptions (#DB from ICEBP),
14407 * Software exceptions (#BP and #OF),
14408 * Hardware exceptions:
14409 * Process the required exceptions and resume guest execution if possible.
14410 */
14411 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14412 Assert(uVector == X86_XCPT_DB);
14413 RT_FALL_THRU();
14414 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14415 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14416 RT_FALL_THRU();
14417 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14418 {
14419 NOREF(uVector);
14420 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14421 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14422 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14423 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14424
14425 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14426 break;
14427 }
14428
14429 default:
14430 {
14431 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14432 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14433 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14434 break;
14435 }
14436 }
14437
14438 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14439 return rcStrict;
14440}
14441
14442
14443/**
14444 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14445 */
14446HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14447{
14448 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14449
14450 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14451 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14452 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14453
14454 /* Evaluate and deliver pending events and resume guest execution. */
14455 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14456 return VINF_SUCCESS;
14457}
14458
14459
14460/**
14461 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14462 */
14463HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14464{
14465 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14466
14467 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14468 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14469 {
14470 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14471 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14472 }
14473
14474 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14475
14476 /*
14477 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14478 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14479 */
14480 uint32_t fIntrState;
14481 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14482 AssertRC(rc);
14483 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14484 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14485 {
14486 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14487 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14488
14489 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14490 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14491 AssertRC(rc);
14492 }
14493
14494 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14495 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14496
14497 /* Evaluate and deliver pending events and resume guest execution. */
14498 return VINF_SUCCESS;
14499}
14500
14501
14502/**
14503 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14504 */
14505HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14506{
14507 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14508 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14509}
14510
14511
14512/**
14513 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14514 */
14515HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14516{
14517 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14518 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14519}
14520
14521
14522/**
14523 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14524 */
14525HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14526{
14527 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14528
14529 /*
14530 * Get the state we need and update the exit history entry.
14531 */
14532 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14533 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14534
14535 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14536 AssertRCReturn(rc, rc);
14537
14538 VBOXSTRICTRC rcStrict;
14539 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14540 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14541 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14542 if (!pExitRec)
14543 {
14544 /*
14545 * Regular CPUID instruction execution.
14546 */
14547 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14548 if (rcStrict == VINF_SUCCESS)
14549 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14550 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14551 {
14552 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14553 rcStrict = VINF_SUCCESS;
14554 }
14555 }
14556 else
14557 {
14558 /*
14559 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14560 */
14561 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14562 AssertRCReturn(rc2, rc2);
14563
14564 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14565 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14566
14567 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14568 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14569
14570 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14571 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14572 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14573 }
14574 return rcStrict;
14575}
14576
14577
14578/**
14579 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14580 */
14581HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14582{
14583 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14584
14585 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14586 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14587 AssertRCReturn(rc, rc);
14588
14589 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14590 return VINF_EM_RAW_EMULATE_INSTR;
14591
14592 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14593 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14594}
14595
14596
14597/**
14598 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14599 */
14600HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14601{
14602 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14603
14604 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14605 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14606 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14607 AssertRCReturn(rc, rc);
14608
14609 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14610 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14611 {
14612 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14613 we must reset offsetting on VM-entry. See @bugref{6634}. */
14614 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14615 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14616 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14617 }
14618 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14619 {
14620 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14621 rcStrict = VINF_SUCCESS;
14622 }
14623 return rcStrict;
14624}
14625
14626
14627/**
14628 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14629 */
14630HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14631{
14632 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14633
14634 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14635 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14636 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14637 AssertRCReturn(rc, rc);
14638
14639 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14640 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14641 {
14642 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14643 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14644 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14645 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14646 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14647 }
14648 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14649 {
14650 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14651 rcStrict = VINF_SUCCESS;
14652 }
14653 return rcStrict;
14654}
14655
14656
14657/**
14658 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14659 */
14660HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14661{
14662 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14663
14664 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14665 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14666 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14667 AssertRCReturn(rc, rc);
14668
14669 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14670 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14671 if (RT_LIKELY(rc == VINF_SUCCESS))
14672 {
14673 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14674 Assert(pVmxTransient->cbExitInstr == 2);
14675 }
14676 else
14677 {
14678 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14679 rc = VERR_EM_INTERPRETER;
14680 }
14681 return rc;
14682}
14683
14684
14685/**
14686 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14687 */
14688HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14689{
14690 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14691
14692 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14693 if (EMAreHypercallInstructionsEnabled(pVCpu))
14694 {
14695 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14696 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14697 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14698 AssertRCReturn(rc, rc);
14699
14700 /* Perform the hypercall. */
14701 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14702 if (rcStrict == VINF_SUCCESS)
14703 {
14704 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14705 AssertRCReturn(rc, rc);
14706 }
14707 else
14708 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14709 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14710 || RT_FAILURE(rcStrict));
14711
14712 /* If the hypercall changes anything other than guest's general-purpose registers,
14713 we would need to reload the guest changed bits here before VM-entry. */
14714 }
14715 else
14716 Log4Func(("Hypercalls not enabled\n"));
14717
14718 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14719 if (RT_FAILURE(rcStrict))
14720 {
14721 hmR0VmxSetPendingXcptUD(pVCpu);
14722 rcStrict = VINF_SUCCESS;
14723 }
14724
14725 return rcStrict;
14726}
14727
14728
14729/**
14730 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14731 */
14732HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14733{
14734 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14735 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14736
14737 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14738 hmR0VmxReadExitQualVmcs(pVmxTransient);
14739 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14740 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14741 AssertRCReturn(rc, rc);
14742
14743 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14744
14745 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14746 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14747 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14748 {
14749 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14750 rcStrict = VINF_SUCCESS;
14751 }
14752 else
14753 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14754 VBOXSTRICTRC_VAL(rcStrict)));
14755 return rcStrict;
14756}
14757
14758
14759/**
14760 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14761 */
14762HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14763{
14764 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14765
14766 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14767 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14768 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14769 AssertRCReturn(rc, rc);
14770
14771 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14772 if (rcStrict == VINF_SUCCESS)
14773 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14774 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14775 {
14776 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14777 rcStrict = VINF_SUCCESS;
14778 }
14779
14780 return rcStrict;
14781}
14782
14783
14784/**
14785 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14786 */
14787HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14788{
14789 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14790
14791 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14792 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14793 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14794 AssertRCReturn(rc, rc);
14795
14796 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14797 if (RT_SUCCESS(rcStrict))
14798 {
14799 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14800 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14801 rcStrict = VINF_SUCCESS;
14802 }
14803
14804 return rcStrict;
14805}
14806
14807
14808/**
14809 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14810 * VM-exit.
14811 */
14812HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14813{
14814 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14815 return VINF_EM_RESET;
14816}
14817
14818
14819/**
14820 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14821 */
14822HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14823{
14824 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14825
14826 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14827 AssertRCReturn(rc, rc);
14828
14829 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14830 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14831 rc = VINF_SUCCESS;
14832 else
14833 rc = VINF_EM_HALT;
14834
14835 if (rc != VINF_SUCCESS)
14836 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14837 return rc;
14838}
14839
14840
14841/**
14842 * VM-exit handler for instructions that result in a \#UD exception delivered to
14843 * the guest.
14844 */
14845HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14846{
14847 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14848 hmR0VmxSetPendingXcptUD(pVCpu);
14849 return VINF_SUCCESS;
14850}
14851
14852
14853/**
14854 * VM-exit handler for expiry of the VMX-preemption timer.
14855 */
14856HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14857{
14858 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14859
14860 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14861 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14862
14863 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14864 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14865 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14866 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14867 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14868}
14869
14870
14871/**
14872 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14873 */
14874HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14875{
14876 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14877
14878 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14879 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14880 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14881 AssertRCReturn(rc, rc);
14882
14883 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14884 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14885 : HM_CHANGED_RAISED_XCPT_MASK);
14886
14887 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14888 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14889
14890 return rcStrict;
14891}
14892
14893
14894/**
14895 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14896 */
14897HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14898{
14899 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14900
14901 /** @todo Enable the new code after finding a reliably guest test-case. */
14902#if 1
14903 return VERR_EM_INTERPRETER;
14904#else
14905 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14906 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14907 hmR0VmxReadExitQualVmcs(pVmxTransient);
14908 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14909 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14910 AssertRCReturn(rc, rc);
14911
14912 /* Paranoia. Ensure this has a memory operand. */
14913 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14914
14915 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14916 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14917 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14918 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14919
14920 RTGCPTR GCPtrDesc;
14921 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14922
14923 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14924 GCPtrDesc, uType);
14925 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14926 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14927 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14928 {
14929 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14930 rcStrict = VINF_SUCCESS;
14931 }
14932 return rcStrict;
14933#endif
14934}
14935
14936
14937/**
14938 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14939 * VM-exit.
14940 */
14941HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14942{
14943 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14944 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14945 AssertRCReturn(rc, rc);
14946
14947 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14948 if (RT_FAILURE(rc))
14949 return rc;
14950
14951 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14952 NOREF(uInvalidReason);
14953
14954#ifdef VBOX_STRICT
14955 uint32_t fIntrState;
14956 uint64_t u64Val;
14957 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14958 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14959 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14960
14961 Log4(("uInvalidReason %u\n", uInvalidReason));
14962 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14963 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14964 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14965
14966 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14967 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14968 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14969 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14970 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14971 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14972 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14973 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14974 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14975 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14976 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14977 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14978 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14979 {
14980 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14981 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14982 }
14983 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14984#endif
14985
14986 return VERR_VMX_INVALID_GUEST_STATE;
14987}
14988
14989/**
14990 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14991 */
14992HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14993{
14994 /*
14995 * Cumulative notes of all recognized but unexpected VM-exits.
14996 *
14997 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14998 * nested-paging is used.
14999 *
15000 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15001 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15002 * this function (and thereby stop VM execution) for handling such instructions.
15003 *
15004 *
15005 * VMX_EXIT_INIT_SIGNAL:
15006 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15007 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15008 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15009 *
15010 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15011 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15012 * See Intel spec. "23.8 Restrictions on VMX operation".
15013 *
15014 * VMX_EXIT_SIPI:
15015 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15016 * activity state is used. We don't make use of it as our guests don't have direct
15017 * access to the host local APIC.
15018 *
15019 * See Intel spec. 25.3 "Other Causes of VM-exits".
15020 *
15021 * VMX_EXIT_IO_SMI:
15022 * VMX_EXIT_SMI:
15023 * This can only happen if we support dual-monitor treatment of SMI, which can be
15024 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15025 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15026 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15027 *
15028 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15029 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15030 *
15031 * VMX_EXIT_ERR_MSR_LOAD:
15032 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15033 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15034 * execution.
15035 *
15036 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15037 *
15038 * VMX_EXIT_ERR_MACHINE_CHECK:
15039 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15040 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15041 * #MC exception abort class exception is raised. We thus cannot assume a
15042 * reasonable chance of continuing any sort of execution and we bail.
15043 *
15044 * See Intel spec. 15.1 "Machine-check Architecture".
15045 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15046 *
15047 * VMX_EXIT_PML_FULL:
15048 * VMX_EXIT_VIRTUALIZED_EOI:
15049 * VMX_EXIT_APIC_WRITE:
15050 * We do not currently support any of these features and thus they are all unexpected
15051 * VM-exits.
15052 *
15053 * VMX_EXIT_GDTR_IDTR_ACCESS:
15054 * VMX_EXIT_LDTR_TR_ACCESS:
15055 * VMX_EXIT_RDRAND:
15056 * VMX_EXIT_RSM:
15057 * VMX_EXIT_VMFUNC:
15058 * VMX_EXIT_ENCLS:
15059 * VMX_EXIT_RDSEED:
15060 * VMX_EXIT_XSAVES:
15061 * VMX_EXIT_XRSTORS:
15062 * VMX_EXIT_UMWAIT:
15063 * VMX_EXIT_TPAUSE:
15064 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15065 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15066 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15067 *
15068 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15069 */
15070 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15071 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15072 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15073}
15074
15075
15076/**
15077 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15078 */
15079HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15080{
15081 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15082
15083 /** @todo Optimize this: We currently drag in the whole MSR state
15084 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15085 * MSRs required. That would require changes to IEM and possibly CPUM too.
15086 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15087 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15088 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15089 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15090 switch (idMsr)
15091 {
15092 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15093 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15094 }
15095
15096 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15097 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15098 AssertRCReturn(rc, rc);
15099
15100 Log4Func(("ecx=%#RX32\n", idMsr));
15101
15102#ifdef VBOX_STRICT
15103 Assert(!pVmxTransient->fIsNestedGuest);
15104 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15105 {
15106 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15107 && idMsr != MSR_K6_EFER)
15108 {
15109 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15110 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15111 }
15112 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15113 {
15114 Assert(pVmcsInfo->pvMsrBitmap);
15115 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15116 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15117 {
15118 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15119 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15120 }
15121 }
15122 }
15123#endif
15124
15125 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15126 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15127 if (rcStrict == VINF_SUCCESS)
15128 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15129 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15130 {
15131 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15132 rcStrict = VINF_SUCCESS;
15133 }
15134 else
15135 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15136
15137 return rcStrict;
15138}
15139
15140
15141/**
15142 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15143 */
15144HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15145{
15146 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15147
15148 /** @todo Optimize this: We currently drag in the whole MSR state
15149 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15150 * MSRs required. That would require changes to IEM and possibly CPUM too.
15151 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15152 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15153 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15154
15155 /*
15156 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15157 * Although we don't need to fetch the base as it will be overwritten shortly, while
15158 * loading guest-state we would also load the entire segment register including limit
15159 * and attributes and thus we need to load them here.
15160 */
15161 switch (idMsr)
15162 {
15163 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15164 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15165 }
15166
15167 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15168 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15169 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15170 AssertRCReturn(rc, rc);
15171
15172 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15173
15174 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15175 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15176
15177 if (rcStrict == VINF_SUCCESS)
15178 {
15179 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15180
15181 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15182 if ( idMsr == MSR_IA32_APICBASE
15183 || ( idMsr >= MSR_IA32_X2APIC_START
15184 && idMsr <= MSR_IA32_X2APIC_END))
15185 {
15186 /*
15187 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15188 * When full APIC register virtualization is implemented we'll have to make
15189 * sure APIC state is saved from the VMCS before IEM changes it.
15190 */
15191 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15192 }
15193 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15194 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15195 else if (idMsr == MSR_K6_EFER)
15196 {
15197 /*
15198 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15199 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15200 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15201 */
15202 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15203 }
15204
15205 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15206 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15207 {
15208 switch (idMsr)
15209 {
15210 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15211 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15212 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15213 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15214 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15215 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15216 default:
15217 {
15218 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15219 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15220 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15221 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15222 break;
15223 }
15224 }
15225 }
15226#ifdef VBOX_STRICT
15227 else
15228 {
15229 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15230 switch (idMsr)
15231 {
15232 case MSR_IA32_SYSENTER_CS:
15233 case MSR_IA32_SYSENTER_EIP:
15234 case MSR_IA32_SYSENTER_ESP:
15235 case MSR_K8_FS_BASE:
15236 case MSR_K8_GS_BASE:
15237 {
15238 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15239 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15240 }
15241
15242 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15243 default:
15244 {
15245 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15246 {
15247 /* EFER MSR writes are always intercepted. */
15248 if (idMsr != MSR_K6_EFER)
15249 {
15250 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15251 idMsr));
15252 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15253 }
15254 }
15255
15256 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15257 {
15258 Assert(pVmcsInfo->pvMsrBitmap);
15259 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15260 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15261 {
15262 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15263 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15264 }
15265 }
15266 break;
15267 }
15268 }
15269 }
15270#endif /* VBOX_STRICT */
15271 }
15272 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15273 {
15274 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15275 rcStrict = VINF_SUCCESS;
15276 }
15277 else
15278 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15279
15280 return rcStrict;
15281}
15282
15283
15284/**
15285 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15286 */
15287HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15288{
15289 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15290
15291 /** @todo The guest has likely hit a contended spinlock. We might want to
15292 * poke a schedule different guest VCPU. */
15293 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15294 if (RT_SUCCESS(rc))
15295 return VINF_EM_RAW_INTERRUPT;
15296
15297 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15298 return rc;
15299}
15300
15301
15302/**
15303 * VM-exit handler for when the TPR value is lowered below the specified
15304 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15305 */
15306HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15307{
15308 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15309 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15310
15311 /*
15312 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15313 * We'll re-evaluate pending interrupts and inject them before the next VM
15314 * entry so we can just continue execution here.
15315 */
15316 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15317 return VINF_SUCCESS;
15318}
15319
15320
15321/**
15322 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15323 * VM-exit.
15324 *
15325 * @retval VINF_SUCCESS when guest execution can continue.
15326 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15327 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15328 * incompatible guest state for VMX execution (real-on-v86 case).
15329 */
15330HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15331{
15332 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15333 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15334
15335 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15336 hmR0VmxReadExitQualVmcs(pVmxTransient);
15337 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15338
15339 VBOXSTRICTRC rcStrict;
15340 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15341 uint64_t const uExitQual = pVmxTransient->uExitQual;
15342 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15343 switch (uAccessType)
15344 {
15345 /*
15346 * MOV to CRx.
15347 */
15348 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15349 {
15350 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15351 AssertRCReturn(rc, rc);
15352
15353 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15354 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15355 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15356 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15357
15358 /*
15359 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15360 * - When nested paging isn't used.
15361 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15362 * - We are executing in the VM debug loop.
15363 */
15364 Assert( iCrReg != 3
15365 || !pVM->hm.s.fNestedPaging
15366 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15367 || pVCpu->hm.s.fUsingDebugLoop);
15368
15369 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15370 Assert( iCrReg != 8
15371 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15372
15373 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15374 AssertMsg( rcStrict == VINF_SUCCESS
15375 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15376
15377 /*
15378 * This is a kludge for handling switches back to real mode when we try to use
15379 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15380 * deal with special selector values, so we have to return to ring-3 and run
15381 * there till the selector values are V86 mode compatible.
15382 *
15383 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15384 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15385 * this function.
15386 */
15387 if ( iCrReg == 0
15388 && rcStrict == VINF_SUCCESS
15389 && !pVM->hm.s.vmx.fUnrestrictedGuest
15390 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15391 && (uOldCr0 & X86_CR0_PE)
15392 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15393 {
15394 /** @todo Check selectors rather than returning all the time. */
15395 Assert(!pVmxTransient->fIsNestedGuest);
15396 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15397 rcStrict = VINF_EM_RESCHEDULE_REM;
15398 }
15399 break;
15400 }
15401
15402 /*
15403 * MOV from CRx.
15404 */
15405 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15406 {
15407 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15408 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15409
15410 /*
15411 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15412 * - When nested paging isn't used.
15413 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15414 * - We are executing in the VM debug loop.
15415 */
15416 Assert( iCrReg != 3
15417 || !pVM->hm.s.fNestedPaging
15418 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15419 || pVCpu->hm.s.fUsingDebugLoop);
15420
15421 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15422 Assert( iCrReg != 8
15423 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15424
15425 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15426 break;
15427 }
15428
15429 /*
15430 * CLTS (Clear Task-Switch Flag in CR0).
15431 */
15432 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15433 {
15434 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15435 break;
15436 }
15437
15438 /*
15439 * LMSW (Load Machine-Status Word into CR0).
15440 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15441 */
15442 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15443 {
15444 RTGCPTR GCPtrEffDst;
15445 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15446 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15447 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15448 if (fMemOperand)
15449 {
15450 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15451 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15452 }
15453 else
15454 GCPtrEffDst = NIL_RTGCPTR;
15455 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15456 break;
15457 }
15458
15459 default:
15460 {
15461 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15462 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15463 }
15464 }
15465
15466 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15467 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15468 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15469
15470 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15471 NOREF(pVM);
15472 return rcStrict;
15473}
15474
15475
15476/**
15477 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15478 * VM-exit.
15479 */
15480HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15481{
15482 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15483 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15484
15485 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15486 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15487 hmR0VmxReadExitQualVmcs(pVmxTransient);
15488 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15489 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15490 | CPUMCTX_EXTRN_EFER);
15491 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15492 AssertRCReturn(rc, rc);
15493
15494 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15495 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15496 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15497 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15498 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15499 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15500 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15501 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15502
15503 /*
15504 * Update exit history to see if this exit can be optimized.
15505 */
15506 VBOXSTRICTRC rcStrict;
15507 PCEMEXITREC pExitRec = NULL;
15508 if ( !fGstStepping
15509 && !fDbgStepping)
15510 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15511 !fIOString
15512 ? !fIOWrite
15513 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15514 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15515 : !fIOWrite
15516 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15517 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15518 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15519 if (!pExitRec)
15520 {
15521 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15522 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15523
15524 uint32_t const cbValue = s_aIOSizes[uIOSize];
15525 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15526 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15527 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15528 if (fIOString)
15529 {
15530 /*
15531 * INS/OUTS - I/O String instruction.
15532 *
15533 * Use instruction-information if available, otherwise fall back on
15534 * interpreting the instruction.
15535 */
15536 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15537 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15538 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15539 if (fInsOutsInfo)
15540 {
15541 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15542 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15543 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15544 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15545 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15546 if (fIOWrite)
15547 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15548 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15549 else
15550 {
15551 /*
15552 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15553 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15554 * See Intel Instruction spec. for "INS".
15555 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15556 */
15557 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15558 }
15559 }
15560 else
15561 rcStrict = IEMExecOne(pVCpu);
15562
15563 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15564 fUpdateRipAlready = true;
15565 }
15566 else
15567 {
15568 /*
15569 * IN/OUT - I/O instruction.
15570 */
15571 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15572 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15573 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15574 if (fIOWrite)
15575 {
15576 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15577 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15578 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15579 && !pCtx->eflags.Bits.u1TF)
15580 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15581 }
15582 else
15583 {
15584 uint32_t u32Result = 0;
15585 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15586 if (IOM_SUCCESS(rcStrict))
15587 {
15588 /* Save result of I/O IN instr. in AL/AX/EAX. */
15589 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15590 }
15591 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15592 && !pCtx->eflags.Bits.u1TF)
15593 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15594 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15595 }
15596 }
15597
15598 if (IOM_SUCCESS(rcStrict))
15599 {
15600 if (!fUpdateRipAlready)
15601 {
15602 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15603 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15604 }
15605
15606 /*
15607 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15608 * while booting Fedora 17 64-bit guest.
15609 *
15610 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15611 */
15612 if (fIOString)
15613 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15614
15615 /*
15616 * If any I/O breakpoints are armed, we need to check if one triggered
15617 * and take appropriate action.
15618 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15619 */
15620 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15621 AssertRCReturn(rc, rc);
15622
15623 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15624 * execution engines about whether hyper BPs and such are pending. */
15625 uint32_t const uDr7 = pCtx->dr[7];
15626 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15627 && X86_DR7_ANY_RW_IO(uDr7)
15628 && (pCtx->cr4 & X86_CR4_DE))
15629 || DBGFBpIsHwIoArmed(pVM)))
15630 {
15631 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15632
15633 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15634 VMMRZCallRing3Disable(pVCpu);
15635 HM_DISABLE_PREEMPT(pVCpu);
15636
15637 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15638
15639 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15640 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15641 {
15642 /* Raise #DB. */
15643 if (fIsGuestDbgActive)
15644 ASMSetDR6(pCtx->dr[6]);
15645 if (pCtx->dr[7] != uDr7)
15646 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15647
15648 hmR0VmxSetPendingXcptDB(pVCpu);
15649 }
15650 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15651 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15652 else if ( rcStrict2 != VINF_SUCCESS
15653 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15654 rcStrict = rcStrict2;
15655 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15656
15657 HM_RESTORE_PREEMPT();
15658 VMMRZCallRing3Enable(pVCpu);
15659 }
15660 }
15661
15662#ifdef VBOX_STRICT
15663 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15664 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15665 Assert(!fIOWrite);
15666 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15667 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15668 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15669 Assert(fIOWrite);
15670 else
15671 {
15672# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15673 * statuses, that the VMM device and some others may return. See
15674 * IOM_SUCCESS() for guidance. */
15675 AssertMsg( RT_FAILURE(rcStrict)
15676 || rcStrict == VINF_SUCCESS
15677 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15678 || rcStrict == VINF_EM_DBG_BREAKPOINT
15679 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15680 || rcStrict == VINF_EM_RAW_TO_R3
15681 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15682# endif
15683 }
15684#endif
15685 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15686 }
15687 else
15688 {
15689 /*
15690 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15691 */
15692 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15693 AssertRCReturn(rc2, rc2);
15694 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15695 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15696 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15697 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15698 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15699 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15700
15701 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15702 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15703
15704 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15705 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15706 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15707 }
15708 return rcStrict;
15709}
15710
15711
15712/**
15713 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15714 * VM-exit.
15715 */
15716HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15717{
15718 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15719
15720 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15721 hmR0VmxReadExitQualVmcs(pVmxTransient);
15722 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15723 {
15724 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15725 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15726 {
15727 uint32_t uErrCode;
15728 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15729 {
15730 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15731 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15732 }
15733 else
15734 uErrCode = 0;
15735
15736 RTGCUINTPTR GCPtrFaultAddress;
15737 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15738 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15739 else
15740 GCPtrFaultAddress = 0;
15741
15742 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15743
15744 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15745 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15746
15747 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15748 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15749 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15750 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15751 }
15752 }
15753
15754 /* Fall back to the interpreter to emulate the task-switch. */
15755 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15756 return VERR_EM_INTERPRETER;
15757}
15758
15759
15760/**
15761 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15762 */
15763HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15764{
15765 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15766
15767 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15768 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15769 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15770 AssertRC(rc);
15771 return VINF_EM_DBG_STEPPED;
15772}
15773
15774
15775/**
15776 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15777 */
15778HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15779{
15780 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15781 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15782
15783 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15784 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15785 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15786 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15787 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15788
15789 /*
15790 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15791 */
15792 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15793 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15794 {
15795 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15796 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15797 {
15798 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15799 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15800 }
15801 }
15802 else
15803 {
15804 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15805 return rcStrict;
15806 }
15807
15808 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15809 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15810 hmR0VmxReadExitQualVmcs(pVmxTransient);
15811 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15812 AssertRCReturn(rc, rc);
15813
15814 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15815 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15816 switch (uAccessType)
15817 {
15818 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15819 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15820 {
15821 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15822 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15823 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15824
15825 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15826 GCPhys &= PAGE_BASE_GC_MASK;
15827 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15828 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15829 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15830
15831 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15832 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15833 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15834 if ( rcStrict == VINF_SUCCESS
15835 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15836 || rcStrict == VERR_PAGE_NOT_PRESENT)
15837 {
15838 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15839 | HM_CHANGED_GUEST_APIC_TPR);
15840 rcStrict = VINF_SUCCESS;
15841 }
15842 break;
15843 }
15844
15845 default:
15846 {
15847 Log4Func(("uAccessType=%#x\n", uAccessType));
15848 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15849 break;
15850 }
15851 }
15852
15853 if (rcStrict != VINF_SUCCESS)
15854 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15855 return rcStrict;
15856}
15857
15858
15859/**
15860 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15861 * VM-exit.
15862 */
15863HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15864{
15865 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15866 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15867
15868 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15869 if (!pVmxTransient->fIsNestedGuest)
15870 {
15871 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15872 if (pVmxTransient->fWasGuestDebugStateActive)
15873 {
15874 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15875 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15876 }
15877
15878 if ( !pVCpu->hm.s.fSingleInstruction
15879 && !pVmxTransient->fWasHyperDebugStateActive)
15880 {
15881 Assert(!DBGFIsStepping(pVCpu));
15882 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15883
15884 /* Don't intercept MOV DRx any more. */
15885 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15886 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15887 AssertRC(rc);
15888
15889 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15890 VMMRZCallRing3Disable(pVCpu);
15891 HM_DISABLE_PREEMPT(pVCpu);
15892
15893 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15894 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15895 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15896
15897 HM_RESTORE_PREEMPT();
15898 VMMRZCallRing3Enable(pVCpu);
15899
15900#ifdef VBOX_WITH_STATISTICS
15901 hmR0VmxReadExitQualVmcs(pVmxTransient);
15902 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15903 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15904 else
15905 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15906#endif
15907 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15908 return VINF_SUCCESS;
15909 }
15910 }
15911
15912 /*
15913 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15914 * The EFER MSR is always up-to-date.
15915 * Update the segment registers and DR7 from the CPU.
15916 */
15917 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15918 hmR0VmxReadExitQualVmcs(pVmxTransient);
15919 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15920 AssertRCReturn(rc, rc);
15921 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15922
15923 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15924 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15925 {
15926 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15927 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15928 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15929 if (RT_SUCCESS(rc))
15930 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15931 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15932 }
15933 else
15934 {
15935 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15936 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15937 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15938 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15939 }
15940
15941 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15942 if (RT_SUCCESS(rc))
15943 {
15944 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15945 AssertRCReturn(rc2, rc2);
15946 return VINF_SUCCESS;
15947 }
15948 return rc;
15949}
15950
15951
15952/**
15953 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15954 * Conditional VM-exit.
15955 */
15956HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15957{
15958 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15959 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15960
15961 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15962 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15963 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15964 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15965 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15966
15967 /*
15968 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15969 */
15970 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15971 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15972 {
15973 /*
15974 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15975 * instruction emulation to inject the original event. Otherwise, injecting the original event
15976 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15977 */
15978 if (!pVCpu->hm.s.Event.fPending)
15979 { /* likely */ }
15980 else
15981 {
15982 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15983#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15984 /** @todo NSTVMX: Think about how this should be handled. */
15985 if (pVmxTransient->fIsNestedGuest)
15986 return VERR_VMX_IPE_3;
15987#endif
15988 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15989 }
15990 }
15991 else
15992 {
15993 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15994 return rcStrict;
15995 }
15996
15997 /*
15998 * Get sufficient state and update the exit history entry.
15999 */
16000 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16001 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16002 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16003 AssertRCReturn(rc, rc);
16004
16005 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16006 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16007 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16008 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16009 if (!pExitRec)
16010 {
16011 /*
16012 * If we succeed, resume guest execution.
16013 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16014 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16015 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16016 * weird case. See @bugref{6043}.
16017 */
16018 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16019 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16020/** @todo bird: We can probably just go straight to IOM here and assume that
16021 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16022 * well. However, we need to address that aliasing workarounds that
16023 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16024 *
16025 * Might also be interesting to see if we can get this done more or
16026 * less locklessly inside IOM. Need to consider the lookup table
16027 * updating and use a bit more carefully first (or do all updates via
16028 * rendezvous) */
16029 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16030 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16031 if ( rcStrict == VINF_SUCCESS
16032 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16033 || rcStrict == VERR_PAGE_NOT_PRESENT)
16034 {
16035 /* Successfully handled MMIO operation. */
16036 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16037 | HM_CHANGED_GUEST_APIC_TPR);
16038 rcStrict = VINF_SUCCESS;
16039 }
16040 }
16041 else
16042 {
16043 /*
16044 * Frequent exit or something needing probing. Call EMHistoryExec.
16045 */
16046 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16047 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16048
16049 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16050 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16051
16052 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16053 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16054 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16055 }
16056 return rcStrict;
16057}
16058
16059
16060/**
16061 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16062 * VM-exit.
16063 */
16064HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16065{
16066 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16067 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16068
16069 hmR0VmxReadExitQualVmcs(pVmxTransient);
16070 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16071 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16072 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16073 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16074 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16075
16076 /*
16077 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16078 */
16079 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16080 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16081 {
16082 /*
16083 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16084 * we shall resolve the nested #PF and re-inject the original event.
16085 */
16086 if (pVCpu->hm.s.Event.fPending)
16087 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16088 }
16089 else
16090 {
16091 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16092 return rcStrict;
16093 }
16094
16095 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16096 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16097 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16098 AssertRCReturn(rc, rc);
16099
16100 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16101 uint64_t const uExitQual = pVmxTransient->uExitQual;
16102 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16103
16104 RTGCUINT uErrorCode = 0;
16105 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16106 uErrorCode |= X86_TRAP_PF_ID;
16107 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16108 uErrorCode |= X86_TRAP_PF_RW;
16109 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16110 uErrorCode |= X86_TRAP_PF_P;
16111
16112 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16113 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16114 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16115
16116 /*
16117 * Handle the pagefault trap for the nested shadow table.
16118 */
16119 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16120 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16121 TRPMResetTrap(pVCpu);
16122
16123 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16124 if ( rcStrict == VINF_SUCCESS
16125 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16126 || rcStrict == VERR_PAGE_NOT_PRESENT)
16127 {
16128 /* Successfully synced our nested page tables. */
16129 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16130 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16131 return VINF_SUCCESS;
16132 }
16133
16134 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16135 return rcStrict;
16136}
16137
16138
16139#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16140/**
16141 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16142 */
16143HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16144{
16145 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16146
16147 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16148 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16149 hmR0VmxReadExitQualVmcs(pVmxTransient);
16150 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16151 | CPUMCTX_EXTRN_HWVIRT
16152 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16153 AssertRCReturn(rc, rc);
16154
16155 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16156
16157 VMXVEXITINFO ExitInfo;
16158 RT_ZERO(ExitInfo);
16159 ExitInfo.uReason = pVmxTransient->uExitReason;
16160 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16161 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16162 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16163 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16164
16165 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16166 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16167 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16168 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16169 {
16170 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16171 rcStrict = VINF_SUCCESS;
16172 }
16173 return rcStrict;
16174}
16175
16176
16177/**
16178 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16179 */
16180HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16181{
16182 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16183
16184 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16185 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16186 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16187 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16188 AssertRCReturn(rc, rc);
16189
16190 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16191
16192 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16193 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16194 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16195 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16196 {
16197 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16198 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16199 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16200 }
16201 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16202 return rcStrict;
16203}
16204
16205
16206/**
16207 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16208 */
16209HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16210{
16211 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16212
16213 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16214 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16215 hmR0VmxReadExitQualVmcs(pVmxTransient);
16216 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16217 | CPUMCTX_EXTRN_HWVIRT
16218 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16219 AssertRCReturn(rc, rc);
16220
16221 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16222
16223 VMXVEXITINFO ExitInfo;
16224 RT_ZERO(ExitInfo);
16225 ExitInfo.uReason = pVmxTransient->uExitReason;
16226 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16227 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16228 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16229 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16230
16231 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16232 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16233 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16234 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16235 {
16236 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16237 rcStrict = VINF_SUCCESS;
16238 }
16239 return rcStrict;
16240}
16241
16242
16243/**
16244 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16245 */
16246HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16247{
16248 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16249
16250 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16251 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16252 hmR0VmxReadExitQualVmcs(pVmxTransient);
16253 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16254 | CPUMCTX_EXTRN_HWVIRT
16255 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16256 AssertRCReturn(rc, rc);
16257
16258 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16259
16260 VMXVEXITINFO ExitInfo;
16261 RT_ZERO(ExitInfo);
16262 ExitInfo.uReason = pVmxTransient->uExitReason;
16263 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16264 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16265 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16266 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16267
16268 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16269 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16270 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16271 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16272 {
16273 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16274 rcStrict = VINF_SUCCESS;
16275 }
16276 return rcStrict;
16277}
16278
16279
16280/**
16281 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16282 */
16283HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16284{
16285 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16286
16287 /*
16288 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16289 * thus might not need to import the shadow VMCS state, it's safer just in case
16290 * code elsewhere dares look at unsynced VMCS fields.
16291 */
16292 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16293 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16294 hmR0VmxReadExitQualVmcs(pVmxTransient);
16295 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16296 | CPUMCTX_EXTRN_HWVIRT
16297 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16298 AssertRCReturn(rc, rc);
16299
16300 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16301
16302 VMXVEXITINFO ExitInfo;
16303 RT_ZERO(ExitInfo);
16304 ExitInfo.uReason = pVmxTransient->uExitReason;
16305 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16306 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16307 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16308 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16309 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16310
16311 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16312 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16313 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16314 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16315 {
16316 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16317 rcStrict = VINF_SUCCESS;
16318 }
16319 return rcStrict;
16320}
16321
16322
16323/**
16324 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16325 */
16326HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16327{
16328 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16329
16330 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16331 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16332 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16333 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16334 AssertRCReturn(rc, rc);
16335
16336 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16337
16338 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16339 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16340 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16341 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16342 {
16343 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16344 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16345 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16346 }
16347 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16348 return rcStrict;
16349}
16350
16351
16352/**
16353 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16354 */
16355HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16356{
16357 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16358
16359 /*
16360 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16361 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16362 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16363 */
16364 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16365 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16366 hmR0VmxReadExitQualVmcs(pVmxTransient);
16367 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16368 | CPUMCTX_EXTRN_HWVIRT
16369 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16370 AssertRCReturn(rc, rc);
16371
16372 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16373
16374 VMXVEXITINFO ExitInfo;
16375 RT_ZERO(ExitInfo);
16376 ExitInfo.uReason = pVmxTransient->uExitReason;
16377 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16378 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16379 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16380 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16381 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16382
16383 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16384 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16385 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16386 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16387 {
16388 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16389 rcStrict = VINF_SUCCESS;
16390 }
16391 return rcStrict;
16392}
16393
16394
16395/**
16396 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16397 */
16398HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16399{
16400 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16401
16402 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16403 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16404 | CPUMCTX_EXTRN_HWVIRT
16405 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16406 AssertRCReturn(rc, rc);
16407
16408 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16409
16410 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16411 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16412 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16413 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16414 {
16415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16416 rcStrict = VINF_SUCCESS;
16417 }
16418 return rcStrict;
16419}
16420
16421
16422/**
16423 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16424 */
16425HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16426{
16427 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16428
16429 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16430 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16431 hmR0VmxReadExitQualVmcs(pVmxTransient);
16432 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16433 | CPUMCTX_EXTRN_HWVIRT
16434 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16435 AssertRCReturn(rc, rc);
16436
16437 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16438
16439 VMXVEXITINFO ExitInfo;
16440 RT_ZERO(ExitInfo);
16441 ExitInfo.uReason = pVmxTransient->uExitReason;
16442 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16443 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16444 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16445 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16446
16447 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16448 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16449 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16450 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16451 {
16452 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16453 rcStrict = VINF_SUCCESS;
16454 }
16455 return rcStrict;
16456}
16457
16458
16459/**
16460 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16461 */
16462HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16463{
16464 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16465
16466 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16467 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16468 hmR0VmxReadExitQualVmcs(pVmxTransient);
16469 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16470 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16471 AssertRCReturn(rc, rc);
16472
16473 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16474
16475 VMXVEXITINFO ExitInfo;
16476 RT_ZERO(ExitInfo);
16477 ExitInfo.uReason = pVmxTransient->uExitReason;
16478 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16479 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16480 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16481 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16482
16483 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16484 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16485 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16486 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16487 {
16488 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16489 rcStrict = VINF_SUCCESS;
16490 }
16491 return rcStrict;
16492}
16493#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16494/** @} */
16495
16496
16497#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16498/** @name Nested-guest VM-exit handlers.
16499 * @{
16500 */
16501/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16502/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16503/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16504
16505/**
16506 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16507 * Conditional VM-exit.
16508 */
16509HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16510{
16511 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16512
16513 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16514
16515 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16516 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16517 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16518
16519 switch (uExitIntType)
16520 {
16521 /*
16522 * Physical NMIs:
16523 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16524 */
16525 case VMX_EXIT_INT_INFO_TYPE_NMI:
16526 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16527
16528 /*
16529 * Hardware exceptions,
16530 * Software exceptions,
16531 * Privileged software exceptions:
16532 * Figure out if the exception must be delivered to the guest or the nested-guest.
16533 */
16534 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16535 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16536 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16537 {
16538 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16539 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16540 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16541 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16542
16543 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16544 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16545 pVmxTransient->uExitIntErrorCode);
16546 if (fIntercept)
16547 {
16548 /* Exit qualification is required for debug and page-fault exceptions. */
16549 hmR0VmxReadExitQualVmcs(pVmxTransient);
16550
16551 /*
16552 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16553 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16554 * length. However, if delivery of a software interrupt, software exception or privileged
16555 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16556 */
16557 VMXVEXITINFO ExitInfo;
16558 RT_ZERO(ExitInfo);
16559 ExitInfo.uReason = pVmxTransient->uExitReason;
16560 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16561 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16562
16563 VMXVEXITEVENTINFO ExitEventInfo;
16564 RT_ZERO(ExitEventInfo);
16565 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16566 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16567 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16568 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16569
16570#ifdef DEBUG_ramshankar
16571 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16572 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16573 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16574 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16575 {
16576 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16577 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16578 }
16579#endif
16580 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16581 }
16582
16583 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16584 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16585 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16586 }
16587
16588 /*
16589 * Software interrupts:
16590 * VM-exits cannot be caused by software interrupts.
16591 *
16592 * External interrupts:
16593 * This should only happen when "acknowledge external interrupts on VM-exit"
16594 * control is set. However, we never set this when executing a guest or
16595 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16596 * the guest.
16597 */
16598 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16599 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16600 default:
16601 {
16602 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16603 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16604 }
16605 }
16606}
16607
16608
16609/**
16610 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16611 * Unconditional VM-exit.
16612 */
16613HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16614{
16615 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16616 return IEMExecVmxVmexitTripleFault(pVCpu);
16617}
16618
16619
16620/**
16621 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16622 */
16623HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16624{
16625 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16626
16627 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16628 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16629 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16630}
16631
16632
16633/**
16634 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16635 */
16636HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16637{
16638 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16639
16640 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16641 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16642 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16643}
16644
16645
16646/**
16647 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16648 * Unconditional VM-exit.
16649 */
16650HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16651{
16652 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16653
16654 hmR0VmxReadExitQualVmcs(pVmxTransient);
16655 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16656 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16657 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16658
16659 VMXVEXITINFO ExitInfo;
16660 RT_ZERO(ExitInfo);
16661 ExitInfo.uReason = pVmxTransient->uExitReason;
16662 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16663 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16664
16665 VMXVEXITEVENTINFO ExitEventInfo;
16666 RT_ZERO(ExitEventInfo);
16667 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16668 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16669 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16670}
16671
16672
16673/**
16674 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16675 */
16676HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16677{
16678 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16679
16680 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16681 {
16682 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16683 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16684 }
16685 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16686}
16687
16688
16689/**
16690 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16691 */
16692HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16693{
16694 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16695
16696 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16697 {
16698 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16699 hmR0VmxReadExitQualVmcs(pVmxTransient);
16700
16701 VMXVEXITINFO ExitInfo;
16702 RT_ZERO(ExitInfo);
16703 ExitInfo.uReason = pVmxTransient->uExitReason;
16704 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16705 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16706 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16707 }
16708 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16709}
16710
16711
16712/**
16713 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16714 */
16715HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16716{
16717 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16718
16719 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16720 {
16721 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16722 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16723 }
16724 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16725}
16726
16727
16728/**
16729 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16730 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16731 */
16732HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16733{
16734 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16735
16736 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16737 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16738
16739 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16740
16741 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16742 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16743 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16744
16745 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16746 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16747 u64VmcsField &= UINT64_C(0xffffffff);
16748
16749 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16750 {
16751 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16752 hmR0VmxReadExitQualVmcs(pVmxTransient);
16753
16754 VMXVEXITINFO ExitInfo;
16755 RT_ZERO(ExitInfo);
16756 ExitInfo.uReason = pVmxTransient->uExitReason;
16757 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16758 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16759 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16760 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16761 }
16762
16763 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16764 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16765 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16766}
16767
16768
16769/**
16770 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16771 */
16772HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16773{
16774 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16775
16776 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16777 {
16778 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16779 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16780 }
16781
16782 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16783}
16784
16785
16786/**
16787 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16788 * Conditional VM-exit.
16789 */
16790HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16791{
16792 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16793
16794 hmR0VmxReadExitQualVmcs(pVmxTransient);
16795 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16796
16797 VBOXSTRICTRC rcStrict;
16798 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16799 switch (uAccessType)
16800 {
16801 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16802 {
16803 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16804 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16805 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16806 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16807
16808 bool fIntercept;
16809 switch (iCrReg)
16810 {
16811 case 0:
16812 case 4:
16813 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16814 break;
16815
16816 case 3:
16817 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16818 break;
16819
16820 case 8:
16821 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16822 break;
16823
16824 default:
16825 fIntercept = false;
16826 break;
16827 }
16828 if (fIntercept)
16829 {
16830 VMXVEXITINFO ExitInfo;
16831 RT_ZERO(ExitInfo);
16832 ExitInfo.uReason = pVmxTransient->uExitReason;
16833 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16834 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16835 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16836 }
16837 else
16838 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16839 break;
16840 }
16841
16842 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16843 {
16844 /*
16845 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16846 * CR2 reads do not cause a VM-exit.
16847 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16848 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16849 */
16850 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16851 if ( iCrReg == 3
16852 || iCrReg == 8)
16853 {
16854 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16855 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16856 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16857 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16858 {
16859 VMXVEXITINFO ExitInfo;
16860 RT_ZERO(ExitInfo);
16861 ExitInfo.uReason = pVmxTransient->uExitReason;
16862 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16863 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16864 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16865 }
16866 else
16867 {
16868 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16869 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16870 }
16871 }
16872 else
16873 {
16874 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16875 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16876 }
16877 break;
16878 }
16879
16880 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16881 {
16882 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16883 Assert(pVmcsNstGst);
16884 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16885 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16886 if ( (uGstHostMask & X86_CR0_TS)
16887 && (uReadShadow & X86_CR0_TS))
16888 {
16889 VMXVEXITINFO ExitInfo;
16890 RT_ZERO(ExitInfo);
16891 ExitInfo.uReason = pVmxTransient->uExitReason;
16892 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16893 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16894 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16895 }
16896 else
16897 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16898 break;
16899 }
16900
16901 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16902 {
16903 RTGCPTR GCPtrEffDst;
16904 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16905 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16906 if (fMemOperand)
16907 {
16908 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16909 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16910 }
16911 else
16912 GCPtrEffDst = NIL_RTGCPTR;
16913
16914 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
16915 {
16916 VMXVEXITINFO ExitInfo;
16917 RT_ZERO(ExitInfo);
16918 ExitInfo.uReason = pVmxTransient->uExitReason;
16919 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16920 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16921 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16922 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16923 }
16924 else
16925 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16926 break;
16927 }
16928
16929 default:
16930 {
16931 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16932 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16933 }
16934 }
16935
16936 if (rcStrict == VINF_IEM_RAISED_XCPT)
16937 {
16938 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16939 rcStrict = VINF_SUCCESS;
16940 }
16941 return rcStrict;
16942}
16943
16944
16945/**
16946 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16947 * Conditional VM-exit.
16948 */
16949HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16950{
16951 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16952
16953 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16954 {
16955 hmR0VmxReadExitQualVmcs(pVmxTransient);
16956 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16957
16958 VMXVEXITINFO ExitInfo;
16959 RT_ZERO(ExitInfo);
16960 ExitInfo.uReason = pVmxTransient->uExitReason;
16961 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16962 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16963 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16964 }
16965 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16966}
16967
16968
16969/**
16970 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16971 * Conditional VM-exit.
16972 */
16973HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16974{
16975 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16976
16977 hmR0VmxReadExitQualVmcs(pVmxTransient);
16978
16979 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16980 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16981 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16982
16983 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16984 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16985 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16986 {
16987 /*
16988 * IN/OUT instruction:
16989 * - Provides VM-exit instruction length.
16990 *
16991 * INS/OUTS instruction:
16992 * - Provides VM-exit instruction length.
16993 * - Provides Guest-linear address.
16994 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16995 */
16996 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16997 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16998
16999 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17000 pVmxTransient->ExitInstrInfo.u = 0;
17001 pVmxTransient->uGuestLinearAddr = 0;
17002
17003 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17004 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17005 if (fIOString)
17006 {
17007 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17008 if (fVmxInsOutsInfo)
17009 {
17010 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17011 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17012 }
17013 }
17014
17015 VMXVEXITINFO ExitInfo;
17016 RT_ZERO(ExitInfo);
17017 ExitInfo.uReason = pVmxTransient->uExitReason;
17018 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17019 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17020 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17021 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17022 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17023 }
17024 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17025}
17026
17027
17028/**
17029 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17030 */
17031HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17032{
17033 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17034
17035 uint32_t fMsrpm;
17036 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17037 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17038 else
17039 fMsrpm = VMXMSRPM_EXIT_RD;
17040
17041 if (fMsrpm & VMXMSRPM_EXIT_RD)
17042 {
17043 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17044 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17045 }
17046 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17047}
17048
17049
17050/**
17051 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17052 */
17053HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17054{
17055 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17056
17057 uint32_t fMsrpm;
17058 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17059 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17060 else
17061 fMsrpm = VMXMSRPM_EXIT_WR;
17062
17063 if (fMsrpm & VMXMSRPM_EXIT_WR)
17064 {
17065 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17066 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17067 }
17068 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17069}
17070
17071
17072/**
17073 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17074 */
17075HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17076{
17077 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17078
17079 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17080 {
17081 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17082 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17083 }
17084 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17085}
17086
17087
17088/**
17089 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17090 * VM-exit.
17091 */
17092HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17093{
17094 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17095
17096 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17097 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17098 VMXVEXITINFO ExitInfo;
17099 RT_ZERO(ExitInfo);
17100 ExitInfo.uReason = pVmxTransient->uExitReason;
17101 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17102 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17103}
17104
17105
17106/**
17107 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17108 */
17109HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17110{
17111 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17112
17113 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17114 {
17115 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17116 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17117 }
17118 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17119}
17120
17121
17122/**
17123 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17124 */
17125HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17126{
17127 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17128
17129 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17130 * PAUSE when executing a nested-guest? If it does not, we would not need
17131 * to check for the intercepts here. Just call VM-exit... */
17132
17133 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17134 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17135 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17136 {
17137 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17138 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17139 }
17140 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17141}
17142
17143
17144/**
17145 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17146 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17147 */
17148HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17149{
17150 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17151
17152 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17153 {
17154 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17155 VMXVEXITINFO ExitInfo;
17156 RT_ZERO(ExitInfo);
17157 ExitInfo.uReason = pVmxTransient->uExitReason;
17158 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17159 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17160 }
17161 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17162}
17163
17164
17165/**
17166 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17167 * VM-exit.
17168 */
17169HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17170{
17171 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17172
17173 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17174 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17175 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17176 hmR0VmxReadExitQualVmcs(pVmxTransient);
17177
17178 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17179
17180 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17181 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17182
17183 VMXVEXITINFO ExitInfo;
17184 RT_ZERO(ExitInfo);
17185 ExitInfo.uReason = pVmxTransient->uExitReason;
17186 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17187 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17188
17189 VMXVEXITEVENTINFO ExitEventInfo;
17190 RT_ZERO(ExitEventInfo);
17191 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17192 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17193 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17194}
17195
17196
17197/**
17198 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17199 * Conditional VM-exit.
17200 */
17201HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17202{
17203 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17204
17205 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17206 hmR0VmxReadExitQualVmcs(pVmxTransient);
17207 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17208}
17209
17210
17211/**
17212 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17213 * Conditional VM-exit.
17214 */
17215HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17216{
17217 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17218
17219 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17220 hmR0VmxReadExitQualVmcs(pVmxTransient);
17221 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17222}
17223
17224
17225/**
17226 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17227 */
17228HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17229{
17230 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17231
17232 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17233 {
17234 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17235 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17236 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17237 }
17238 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17239}
17240
17241
17242/**
17243 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17244 */
17245HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17246{
17247 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17248
17249 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17250 {
17251 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17252 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17253 }
17254 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17255}
17256
17257
17258/**
17259 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17260 */
17261HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17262{
17263 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17264
17265 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17266 {
17267 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17268 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17269 hmR0VmxReadExitQualVmcs(pVmxTransient);
17270 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17271
17272 VMXVEXITINFO ExitInfo;
17273 RT_ZERO(ExitInfo);
17274 ExitInfo.uReason = pVmxTransient->uExitReason;
17275 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17276 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17277 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17278 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17279 }
17280 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17281}
17282
17283
17284/**
17285 * Nested-guest VM-exit handler for invalid-guest state
17286 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17287 */
17288HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17289{
17290 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17291
17292 /*
17293 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17294 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17295 * Handle it like it's in an invalid guest state of the outer guest.
17296 *
17297 * When the fast path is implemented, this should be changed to cause the corresponding
17298 * nested-guest VM-exit.
17299 */
17300 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17301}
17302
17303
17304/**
17305 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17306 * and only provide the instruction length.
17307 *
17308 * Unconditional VM-exit.
17309 */
17310HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17311{
17312 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17313
17314#ifdef VBOX_STRICT
17315 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17316 switch (pVmxTransient->uExitReason)
17317 {
17318 case VMX_EXIT_ENCLS:
17319 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17320 break;
17321
17322 case VMX_EXIT_VMFUNC:
17323 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17324 break;
17325 }
17326#endif
17327
17328 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17329 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17330}
17331
17332
17333/**
17334 * Nested-guest VM-exit handler for instructions that provide instruction length as
17335 * well as more information.
17336 *
17337 * Unconditional VM-exit.
17338 */
17339HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17340{
17341 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17342
17343#ifdef VBOX_STRICT
17344 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17345 switch (pVmxTransient->uExitReason)
17346 {
17347 case VMX_EXIT_GDTR_IDTR_ACCESS:
17348 case VMX_EXIT_LDTR_TR_ACCESS:
17349 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17350 break;
17351
17352 case VMX_EXIT_RDRAND:
17353 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17354 break;
17355
17356 case VMX_EXIT_RDSEED:
17357 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17358 break;
17359
17360 case VMX_EXIT_XSAVES:
17361 case VMX_EXIT_XRSTORS:
17362 /** @todo NSTVMX: Verify XSS-bitmap. */
17363 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17364 break;
17365
17366 case VMX_EXIT_UMWAIT:
17367 case VMX_EXIT_TPAUSE:
17368 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17369 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17370 break;
17371 }
17372#endif
17373
17374 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17375 hmR0VmxReadExitQualVmcs(pVmxTransient);
17376 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17377
17378 VMXVEXITINFO ExitInfo;
17379 RT_ZERO(ExitInfo);
17380 ExitInfo.uReason = pVmxTransient->uExitReason;
17381 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17382 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17383 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17384 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17385}
17386
17387/** @} */
17388#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17389
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