VirtualBox

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

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

VMM/HMVMX: Moved uHostRIP and uHostRSP into the VMXVMCSINFO as that seems an more appropriate place for thhem.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 731.9 KB
Line 
1/* $Id: HMVMXR0.cpp 87490 2021-01-29 18:42:54Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2020 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hmr0.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hmr0.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 *
192 * Note: The members are ordered and aligned such that the most
193 * frequently used ones (in the guest execution loop) fall within
194 * the first cache line.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
199 uint32_t fVmcsFieldsRead;
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 uint8_t abAlignment0[3];
203
204 /** Whether the VM-exit was caused by a page-fault during delivery of an
205 * external interrupt or NMI. */
206 bool fVectoringPF;
207 /** Whether the VM-exit was caused by a page-fault during delivery of a
208 * contributory exception or a page-fault. */
209 bool fVectoringDoublePF;
210 /** Whether the VM-entry failed or not. */
211 bool fVMEntryFailed;
212 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
213 * area after VM-exit. */
214 bool fRemoveTscAuxMsr;
215 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
216 bool fUpdatedTscOffsettingAndPreemptTimer;
217 /** Whether we are currently executing a nested-guest. */
218 bool fIsNestedGuest;
219 /** Whether the guest debug state was active at the time of VM-exit. */
220 bool fWasGuestDebugStateActive;
221 /** Whether the hyper debug state was active at the time of VM-exit. */
222 bool fWasHyperDebugStateActive;
223
224 /** The basic VM-exit reason. */
225 uint32_t uExitReason;
226 /** The VM-exit interruption error code. */
227 uint32_t uExitIntErrorCode;
228
229 /** The host's rflags/eflags. */
230 RTCCUINTREG fEFlags;
231
232 /** The VM-exit exit code qualification. */
233 uint64_t uExitQual;
234
235 /** The VMCS info. object. */
236 PVMXVMCSINFO pVmcsInfo;
237
238 /** The VM-exit interruption-information field. */
239 uint32_t uExitIntInfo;
240 /** The VM-exit instruction-length field. */
241 uint32_t cbExitInstr;
242
243 /** The VM-exit instruction-information field. */
244 VMXEXITINSTRINFO ExitInstrInfo;
245 /** IDT-vectoring information field. */
246 uint32_t uIdtVectoringInfo;
247
248 /** IDT-vectoring error code. */
249 uint32_t uIdtVectoringErrorCode;
250 uint32_t u32Alignment0;
251
252 /** The Guest-linear address. */
253 uint64_t uGuestLinearAddr;
254
255 /** The Guest-physical address. */
256 uint64_t uGuestPhysicalAddr;
257
258 /** The Guest pending-debug exceptions. */
259 uint64_t uGuestPendingDbgXcpts;
260
261 /** The VM-entry interruption-information field. */
262 uint32_t uEntryIntInfo;
263 /** The VM-entry exception error code field. */
264 uint32_t uEntryXcptErrorCode;
265
266 /** The VM-entry instruction length field. */
267 uint32_t cbEntryInstr;
268} VMXTRANSIENT;
269AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, fVmcsFieldsRead, 8);
271AssertCompileMemberAlignment(VMXTRANSIENT, fVectoringPF, 8);
272AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, 8);
273AssertCompileMemberAlignment(VMXTRANSIENT, fEFlags, 8);
274AssertCompileMemberAlignment(VMXTRANSIENT, uExitQual, 8);
275AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, 8);
276AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, 8);
277AssertCompileMemberAlignment(VMXTRANSIENT, ExitInstrInfo, 8);
278AssertCompileMemberAlignment(VMXTRANSIENT, uIdtVectoringErrorCode, 8);
279AssertCompileMemberAlignment(VMXTRANSIENT, uGuestLinearAddr, 8);
280AssertCompileMemberAlignment(VMXTRANSIENT, uGuestPhysicalAddr, 8);
281AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, 8);
282AssertCompileMemberAlignment(VMXTRANSIENT, cbEntryInstr, 8);
283/** Pointer to VMX transient state. */
284typedef VMXTRANSIENT *PVMXTRANSIENT;
285/** Pointer to a const VMX transient state. */
286typedef const VMXTRANSIENT *PCVMXTRANSIENT;
287
288/**
289 * VMX page allocation information.
290 */
291typedef struct
292{
293 uint32_t fValid; /**< Whether to allocate this page (e.g, based on a CPU feature). */
294 uint32_t uPadding0; /**< Padding to ensure array of these structs are aligned to a multiple of 8. */
295 PRTHCPHYS pHCPhys; /**< Where to store the host-physical address of the allocation. */
296 PRTR0PTR ppVirt; /**< Where to store the host-virtual address of the allocation. */
297} VMXPAGEALLOCINFO;
298/** Pointer to VMX page-allocation info. */
299typedef VMXPAGEALLOCINFO *PVMXPAGEALLOCINFO;
300/** Pointer to a const VMX page-allocation info. */
301typedef const VMXPAGEALLOCINFO *PCVMXPAGEALLOCINFO;
302AssertCompileSizeAlignment(VMXPAGEALLOCINFO, 8);
303
304/**
305 * Memory operand read or write access.
306 */
307typedef enum VMXMEMACCESS
308{
309 VMXMEMACCESS_READ = 0,
310 VMXMEMACCESS_WRITE = 1
311} VMXMEMACCESS;
312
313/**
314 * VMX VM-exit handler.
315 *
316 * @returns Strict VBox status code (i.e. informational status codes too).
317 * @param pVCpu The cross context virtual CPU structure.
318 * @param pVmxTransient The VMX-transient structure.
319 */
320#ifndef HMVMX_USE_FUNCTION_TABLE
321typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
322#else
323typedef DECLCALLBACKTYPE(VBOXSTRICTRC, FNVMXEXITHANDLER,(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient));
324/** Pointer to VM-exit handler. */
325typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
326#endif
327
328/**
329 * VMX VM-exit handler, non-strict status code.
330 *
331 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
332 *
333 * @returns VBox status code, no informational status code returned.
334 * @param pVCpu The cross context virtual CPU structure.
335 * @param pVmxTransient The VMX-transient structure.
336 *
337 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
338 * use of that status code will be replaced with VINF_EM_SOMETHING
339 * later when switching over to IEM.
340 */
341#ifndef HMVMX_USE_FUNCTION_TABLE
342typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
343#else
344typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
345#endif
346
347
348/*********************************************************************************************************************************
349* Internal Functions *
350*********************************************************************************************************************************/
351#ifndef HMVMX_USE_FUNCTION_TABLE
352DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
353# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
354# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
355#else
356# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
357# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
358#endif
359#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
360DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
361#endif
362
363static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
364
365/** @name VM-exit handler prototypes.
366 * @{
367 */
368static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
369static FNVMXEXITHANDLER hmR0VmxExitExtInt;
370static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
371static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
372static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
373static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
374static FNVMXEXITHANDLER hmR0VmxExitCpuid;
375static FNVMXEXITHANDLER hmR0VmxExitGetsec;
376static FNVMXEXITHANDLER hmR0VmxExitHlt;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
378static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
379static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
380static FNVMXEXITHANDLER hmR0VmxExitVmcall;
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382static FNVMXEXITHANDLER hmR0VmxExitVmclear;
383static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
384static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
385static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
386static FNVMXEXITHANDLER hmR0VmxExitVmread;
387static FNVMXEXITHANDLER hmR0VmxExitVmresume;
388static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
389static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
390static FNVMXEXITHANDLER hmR0VmxExitVmxon;
391static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
392#endif
393static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
394static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
395static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
396static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
397static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
398static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
399static FNVMXEXITHANDLER hmR0VmxExitMwait;
400static FNVMXEXITHANDLER hmR0VmxExitMtf;
401static FNVMXEXITHANDLER hmR0VmxExitMonitor;
402static FNVMXEXITHANDLER hmR0VmxExitPause;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
404static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
405static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
406static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
407static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
408static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
410static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
411static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
414static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
415/** @} */
416
417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
418/** @name Nested-guest VM-exit handler prototypes.
419 * @{
420 */
421static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
422static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
425static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
426static FNVMXEXITHANDLER hmR0VmxExitHltNested;
427static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
428static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
429static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
430static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
431static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
432static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
433static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
434static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
435static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
436static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
437static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
438static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
439static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
440static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
441static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
442static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
443static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
444static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
445static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
446static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
447static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
448static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
449static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
450/** @} */
451#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
452
453
454/*********************************************************************************************************************************
455* Global Variables *
456*********************************************************************************************************************************/
457#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
458/**
459 * Array of all VMCS fields.
460 * Any fields added to the VT-x spec. should be added here.
461 *
462 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
463 * of nested-guests.
464 */
465static const uint32_t g_aVmcsFields[] =
466{
467 /* 16-bit control fields. */
468 VMX_VMCS16_VPID,
469 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
470 VMX_VMCS16_EPTP_INDEX,
471
472 /* 16-bit guest-state fields. */
473 VMX_VMCS16_GUEST_ES_SEL,
474 VMX_VMCS16_GUEST_CS_SEL,
475 VMX_VMCS16_GUEST_SS_SEL,
476 VMX_VMCS16_GUEST_DS_SEL,
477 VMX_VMCS16_GUEST_FS_SEL,
478 VMX_VMCS16_GUEST_GS_SEL,
479 VMX_VMCS16_GUEST_LDTR_SEL,
480 VMX_VMCS16_GUEST_TR_SEL,
481 VMX_VMCS16_GUEST_INTR_STATUS,
482 VMX_VMCS16_GUEST_PML_INDEX,
483
484 /* 16-bits host-state fields. */
485 VMX_VMCS16_HOST_ES_SEL,
486 VMX_VMCS16_HOST_CS_SEL,
487 VMX_VMCS16_HOST_SS_SEL,
488 VMX_VMCS16_HOST_DS_SEL,
489 VMX_VMCS16_HOST_FS_SEL,
490 VMX_VMCS16_HOST_GS_SEL,
491 VMX_VMCS16_HOST_TR_SEL,
492
493 /* 64-bit control fields. */
494 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
495 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
496 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
497 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
498 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
499 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
501 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
502 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
503 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
504 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
505 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
506 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
507 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
508 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
509 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
510 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
511 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
512 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
513 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
514 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
515 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
516 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
517 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
518 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
519 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
520 VMX_VMCS64_CTRL_EPTP_FULL,
521 VMX_VMCS64_CTRL_EPTP_HIGH,
522 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
523 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
524 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
525 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
526 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
527 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
528 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
529 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
530 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
531 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
532 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
533 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
534 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
535 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
536 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
537 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
538 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
539 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
540 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
541 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
542 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
543 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
544
545 /* 64-bit read-only data fields. */
546 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
547 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
548
549 /* 64-bit guest-state fields. */
550 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
551 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
552 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
553 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
554 VMX_VMCS64_GUEST_PAT_FULL,
555 VMX_VMCS64_GUEST_PAT_HIGH,
556 VMX_VMCS64_GUEST_EFER_FULL,
557 VMX_VMCS64_GUEST_EFER_HIGH,
558 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
559 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
560 VMX_VMCS64_GUEST_PDPTE0_FULL,
561 VMX_VMCS64_GUEST_PDPTE0_HIGH,
562 VMX_VMCS64_GUEST_PDPTE1_FULL,
563 VMX_VMCS64_GUEST_PDPTE1_HIGH,
564 VMX_VMCS64_GUEST_PDPTE2_FULL,
565 VMX_VMCS64_GUEST_PDPTE2_HIGH,
566 VMX_VMCS64_GUEST_PDPTE3_FULL,
567 VMX_VMCS64_GUEST_PDPTE3_HIGH,
568 VMX_VMCS64_GUEST_BNDCFGS_FULL,
569 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
570
571 /* 64-bit host-state fields. */
572 VMX_VMCS64_HOST_PAT_FULL,
573 VMX_VMCS64_HOST_PAT_HIGH,
574 VMX_VMCS64_HOST_EFER_FULL,
575 VMX_VMCS64_HOST_EFER_HIGH,
576 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
577 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
578
579 /* 32-bit control fields. */
580 VMX_VMCS32_CTRL_PIN_EXEC,
581 VMX_VMCS32_CTRL_PROC_EXEC,
582 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
583 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
584 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
585 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
586 VMX_VMCS32_CTRL_EXIT,
587 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
588 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
589 VMX_VMCS32_CTRL_ENTRY,
590 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
591 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
592 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
593 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
594 VMX_VMCS32_CTRL_TPR_THRESHOLD,
595 VMX_VMCS32_CTRL_PROC_EXEC2,
596 VMX_VMCS32_CTRL_PLE_GAP,
597 VMX_VMCS32_CTRL_PLE_WINDOW,
598
599 /* 32-bits read-only fields. */
600 VMX_VMCS32_RO_VM_INSTR_ERROR,
601 VMX_VMCS32_RO_EXIT_REASON,
602 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
603 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
604 VMX_VMCS32_RO_IDT_VECTORING_INFO,
605 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
606 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
607 VMX_VMCS32_RO_EXIT_INSTR_INFO,
608
609 /* 32-bit guest-state fields. */
610 VMX_VMCS32_GUEST_ES_LIMIT,
611 VMX_VMCS32_GUEST_CS_LIMIT,
612 VMX_VMCS32_GUEST_SS_LIMIT,
613 VMX_VMCS32_GUEST_DS_LIMIT,
614 VMX_VMCS32_GUEST_FS_LIMIT,
615 VMX_VMCS32_GUEST_GS_LIMIT,
616 VMX_VMCS32_GUEST_LDTR_LIMIT,
617 VMX_VMCS32_GUEST_TR_LIMIT,
618 VMX_VMCS32_GUEST_GDTR_LIMIT,
619 VMX_VMCS32_GUEST_IDTR_LIMIT,
620 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
621 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
622 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
623 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
624 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
625 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
626 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
627 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
628 VMX_VMCS32_GUEST_INT_STATE,
629 VMX_VMCS32_GUEST_ACTIVITY_STATE,
630 VMX_VMCS32_GUEST_SMBASE,
631 VMX_VMCS32_GUEST_SYSENTER_CS,
632 VMX_VMCS32_PREEMPT_TIMER_VALUE,
633
634 /* 32-bit host-state fields. */
635 VMX_VMCS32_HOST_SYSENTER_CS,
636
637 /* Natural-width control fields. */
638 VMX_VMCS_CTRL_CR0_MASK,
639 VMX_VMCS_CTRL_CR4_MASK,
640 VMX_VMCS_CTRL_CR0_READ_SHADOW,
641 VMX_VMCS_CTRL_CR4_READ_SHADOW,
642 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
643 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
644 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
645 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
646
647 /* Natural-width read-only data fields. */
648 VMX_VMCS_RO_EXIT_QUALIFICATION,
649 VMX_VMCS_RO_IO_RCX,
650 VMX_VMCS_RO_IO_RSI,
651 VMX_VMCS_RO_IO_RDI,
652 VMX_VMCS_RO_IO_RIP,
653 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
654
655 /* Natural-width guest-state field */
656 VMX_VMCS_GUEST_CR0,
657 VMX_VMCS_GUEST_CR3,
658 VMX_VMCS_GUEST_CR4,
659 VMX_VMCS_GUEST_ES_BASE,
660 VMX_VMCS_GUEST_CS_BASE,
661 VMX_VMCS_GUEST_SS_BASE,
662 VMX_VMCS_GUEST_DS_BASE,
663 VMX_VMCS_GUEST_FS_BASE,
664 VMX_VMCS_GUEST_GS_BASE,
665 VMX_VMCS_GUEST_LDTR_BASE,
666 VMX_VMCS_GUEST_TR_BASE,
667 VMX_VMCS_GUEST_GDTR_BASE,
668 VMX_VMCS_GUEST_IDTR_BASE,
669 VMX_VMCS_GUEST_DR7,
670 VMX_VMCS_GUEST_RSP,
671 VMX_VMCS_GUEST_RIP,
672 VMX_VMCS_GUEST_RFLAGS,
673 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
674 VMX_VMCS_GUEST_SYSENTER_ESP,
675 VMX_VMCS_GUEST_SYSENTER_EIP,
676
677 /* Natural-width host-state fields */
678 VMX_VMCS_HOST_CR0,
679 VMX_VMCS_HOST_CR3,
680 VMX_VMCS_HOST_CR4,
681 VMX_VMCS_HOST_FS_BASE,
682 VMX_VMCS_HOST_GS_BASE,
683 VMX_VMCS_HOST_TR_BASE,
684 VMX_VMCS_HOST_GDTR_BASE,
685 VMX_VMCS_HOST_IDTR_BASE,
686 VMX_VMCS_HOST_SYSENTER_ESP,
687 VMX_VMCS_HOST_SYSENTER_EIP,
688 VMX_VMCS_HOST_RSP,
689 VMX_VMCS_HOST_RIP
690};
691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
692
693#ifdef VBOX_STRICT
694static const uint32_t g_aVmcsSegBase[] =
695{
696 VMX_VMCS_GUEST_ES_BASE,
697 VMX_VMCS_GUEST_CS_BASE,
698 VMX_VMCS_GUEST_SS_BASE,
699 VMX_VMCS_GUEST_DS_BASE,
700 VMX_VMCS_GUEST_FS_BASE,
701 VMX_VMCS_GUEST_GS_BASE
702};
703static const uint32_t g_aVmcsSegSel[] =
704{
705 VMX_VMCS16_GUEST_ES_SEL,
706 VMX_VMCS16_GUEST_CS_SEL,
707 VMX_VMCS16_GUEST_SS_SEL,
708 VMX_VMCS16_GUEST_DS_SEL,
709 VMX_VMCS16_GUEST_FS_SEL,
710 VMX_VMCS16_GUEST_GS_SEL
711};
712static const uint32_t g_aVmcsSegLimit[] =
713{
714 VMX_VMCS32_GUEST_ES_LIMIT,
715 VMX_VMCS32_GUEST_CS_LIMIT,
716 VMX_VMCS32_GUEST_SS_LIMIT,
717 VMX_VMCS32_GUEST_DS_LIMIT,
718 VMX_VMCS32_GUEST_FS_LIMIT,
719 VMX_VMCS32_GUEST_GS_LIMIT
720};
721static const uint32_t g_aVmcsSegAttr[] =
722{
723 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
724 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
725 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
726 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
727 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
728 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
729};
730AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
731AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
732AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
733AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
734#endif /* VBOX_STRICT */
735
736#ifdef HMVMX_USE_FUNCTION_TABLE
737/**
738 * VMX_EXIT dispatch table.
739 */
740static const struct CLANG11NOTHROWWEIRDNESS { PFNVMXEXITHANDLER pfn; } g_aVMExitHandlers[VMX_EXIT_MAX + 1] =
741{
742 /* 0 VMX_EXIT_XCPT_OR_NMI */ { hmR0VmxExitXcptOrNmi },
743 /* 1 VMX_EXIT_EXT_INT */ { hmR0VmxExitExtInt },
744 /* 2 VMX_EXIT_TRIPLE_FAULT */ { hmR0VmxExitTripleFault },
745 /* 3 VMX_EXIT_INIT_SIGNAL */ { hmR0VmxExitErrUnexpected },
746 /* 4 VMX_EXIT_SIPI */ { hmR0VmxExitErrUnexpected },
747 /* 5 VMX_EXIT_IO_SMI */ { hmR0VmxExitErrUnexpected },
748 /* 6 VMX_EXIT_SMI */ { hmR0VmxExitErrUnexpected },
749 /* 7 VMX_EXIT_INT_WINDOW */ { hmR0VmxExitIntWindow },
750 /* 8 VMX_EXIT_NMI_WINDOW */ { hmR0VmxExitNmiWindow },
751 /* 9 VMX_EXIT_TASK_SWITCH */ { hmR0VmxExitTaskSwitch },
752 /* 10 VMX_EXIT_CPUID */ { hmR0VmxExitCpuid },
753 /* 11 VMX_EXIT_GETSEC */ { hmR0VmxExitGetsec },
754 /* 12 VMX_EXIT_HLT */ { hmR0VmxExitHlt },
755 /* 13 VMX_EXIT_INVD */ { hmR0VmxExitInvd },
756 /* 14 VMX_EXIT_INVLPG */ { hmR0VmxExitInvlpg },
757 /* 15 VMX_EXIT_RDPMC */ { hmR0VmxExitRdpmc },
758 /* 16 VMX_EXIT_RDTSC */ { hmR0VmxExitRdtsc },
759 /* 17 VMX_EXIT_RSM */ { hmR0VmxExitErrUnexpected },
760 /* 18 VMX_EXIT_VMCALL */ { hmR0VmxExitVmcall },
761#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
762 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitVmclear },
763 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitVmlaunch },
764 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitVmptrld },
765 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitVmptrst },
766 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitVmread },
767 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitVmresume },
768 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitVmwrite },
769 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitVmxoff },
770 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitVmxon },
771#else
772 /* 19 VMX_EXIT_VMCLEAR */ { hmR0VmxExitSetPendingXcptUD },
773 /* 20 VMX_EXIT_VMLAUNCH */ { hmR0VmxExitSetPendingXcptUD },
774 /* 21 VMX_EXIT_VMPTRLD */ { hmR0VmxExitSetPendingXcptUD },
775 /* 22 VMX_EXIT_VMPTRST */ { hmR0VmxExitSetPendingXcptUD },
776 /* 23 VMX_EXIT_VMREAD */ { hmR0VmxExitSetPendingXcptUD },
777 /* 24 VMX_EXIT_VMRESUME */ { hmR0VmxExitSetPendingXcptUD },
778 /* 25 VMX_EXIT_VMWRITE */ { hmR0VmxExitSetPendingXcptUD },
779 /* 26 VMX_EXIT_VMXOFF */ { hmR0VmxExitSetPendingXcptUD },
780 /* 27 VMX_EXIT_VMXON */ { hmR0VmxExitSetPendingXcptUD },
781#endif
782 /* 28 VMX_EXIT_MOV_CRX */ { hmR0VmxExitMovCRx },
783 /* 29 VMX_EXIT_MOV_DRX */ { hmR0VmxExitMovDRx },
784 /* 30 VMX_EXIT_IO_INSTR */ { hmR0VmxExitIoInstr },
785 /* 31 VMX_EXIT_RDMSR */ { hmR0VmxExitRdmsr },
786 /* 32 VMX_EXIT_WRMSR */ { hmR0VmxExitWrmsr },
787 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ { hmR0VmxExitErrInvalidGuestState },
788 /* 34 VMX_EXIT_ERR_MSR_LOAD */ { hmR0VmxExitErrUnexpected },
789 /* 35 UNDEFINED */ { hmR0VmxExitErrUnexpected },
790 /* 36 VMX_EXIT_MWAIT */ { hmR0VmxExitMwait },
791 /* 37 VMX_EXIT_MTF */ { hmR0VmxExitMtf },
792 /* 38 UNDEFINED */ { hmR0VmxExitErrUnexpected },
793 /* 39 VMX_EXIT_MONITOR */ { hmR0VmxExitMonitor },
794 /* 40 VMX_EXIT_PAUSE */ { hmR0VmxExitPause },
795 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ { hmR0VmxExitErrUnexpected },
796 /* 42 UNDEFINED */ { hmR0VmxExitErrUnexpected },
797 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ { hmR0VmxExitTprBelowThreshold },
798 /* 44 VMX_EXIT_APIC_ACCESS */ { hmR0VmxExitApicAccess },
799 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ { hmR0VmxExitErrUnexpected },
800 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ { hmR0VmxExitErrUnexpected },
801 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ { hmR0VmxExitErrUnexpected },
802 /* 48 VMX_EXIT_EPT_VIOLATION */ { hmR0VmxExitEptViolation },
803 /* 49 VMX_EXIT_EPT_MISCONFIG */ { hmR0VmxExitEptMisconfig },
804 /* 50 VMX_EXIT_INVEPT */ { hmR0VmxExitSetPendingXcptUD },
805 /* 51 VMX_EXIT_RDTSCP */ { hmR0VmxExitRdtscp },
806 /* 52 VMX_EXIT_PREEMPT_TIMER */ { hmR0VmxExitPreemptTimer },
807#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
808 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitInvvpid },
809#else
810 /* 53 VMX_EXIT_INVVPID */ { hmR0VmxExitSetPendingXcptUD },
811#endif
812 /* 54 VMX_EXIT_WBINVD */ { hmR0VmxExitWbinvd },
813 /* 55 VMX_EXIT_XSETBV */ { hmR0VmxExitXsetbv },
814 /* 56 VMX_EXIT_APIC_WRITE */ { hmR0VmxExitErrUnexpected },
815 /* 57 VMX_EXIT_RDRAND */ { hmR0VmxExitErrUnexpected },
816 /* 58 VMX_EXIT_INVPCID */ { hmR0VmxExitInvpcid },
817 /* 59 VMX_EXIT_VMFUNC */ { hmR0VmxExitErrUnexpected },
818 /* 60 VMX_EXIT_ENCLS */ { hmR0VmxExitErrUnexpected },
819 /* 61 VMX_EXIT_RDSEED */ { hmR0VmxExitErrUnexpected },
820 /* 62 VMX_EXIT_PML_FULL */ { hmR0VmxExitErrUnexpected },
821 /* 63 VMX_EXIT_XSAVES */ { hmR0VmxExitErrUnexpected },
822 /* 64 VMX_EXIT_XRSTORS */ { hmR0VmxExitErrUnexpected },
823 /* 65 UNDEFINED */ { hmR0VmxExitErrUnexpected },
824 /* 66 VMX_EXIT_SPP_EVENT */ { hmR0VmxExitErrUnexpected },
825 /* 67 VMX_EXIT_UMWAIT */ { hmR0VmxExitErrUnexpected },
826 /* 68 VMX_EXIT_TPAUSE */ { hmR0VmxExitErrUnexpected },
827};
828#endif /* HMVMX_USE_FUNCTION_TABLE */
829
830#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
831static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
832{
833 /* 0 */ "(Not Used)",
834 /* 1 */ "VMCALL executed in VMX root operation.",
835 /* 2 */ "VMCLEAR with invalid physical address.",
836 /* 3 */ "VMCLEAR with VMXON pointer.",
837 /* 4 */ "VMLAUNCH with non-clear VMCS.",
838 /* 5 */ "VMRESUME with non-launched VMCS.",
839 /* 6 */ "VMRESUME after VMXOFF",
840 /* 7 */ "VM-entry with invalid control fields.",
841 /* 8 */ "VM-entry with invalid host state fields.",
842 /* 9 */ "VMPTRLD with invalid physical address.",
843 /* 10 */ "VMPTRLD with VMXON pointer.",
844 /* 11 */ "VMPTRLD with incorrect revision identifier.",
845 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
846 /* 13 */ "VMWRITE to read-only VMCS component.",
847 /* 14 */ "(Not Used)",
848 /* 15 */ "VMXON executed in VMX root operation.",
849 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
850 /* 17 */ "VM-entry with non-launched executing VMCS.",
851 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
852 /* 19 */ "VMCALL with non-clear VMCS.",
853 /* 20 */ "VMCALL with invalid VM-exit control fields.",
854 /* 21 */ "(Not Used)",
855 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
856 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
857 /* 24 */ "VMCALL with invalid SMM-monitor features.",
858 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
859 /* 26 */ "VM-entry with events blocked by MOV SS.",
860 /* 27 */ "(Not Used)",
861 /* 28 */ "Invalid operand to INVEPT/INVVPID."
862};
863#endif /* VBOX_STRICT && LOG_ENABLED */
864
865
866/**
867 * Checks if the given MSR is part of the lastbranch-from-IP MSR stack.
868 * @returns @c true if it's part of LBR stack, @c false otherwise.
869 *
870 * @param pVM The cross context VM structure.
871 * @param idMsr The MSR.
872 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
873 * Optional, can be NULL.
874 *
875 * @remarks Must only be called when LBR is enabled.
876 */
877DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchFromMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
878{
879 Assert(pVM->hm.s.vmx.fLbr);
880 Assert(pVM->hm.s.vmx.idLbrFromIpMsrFirst);
881 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
882 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrFromIpMsrFirst;
883 if (idxMsr < cLbrStack)
884 {
885 if (pidxMsr)
886 *pidxMsr = idxMsr;
887 return true;
888 }
889 return false;
890}
891
892
893/**
894 * Checks if the given MSR is part of the lastbranch-to-IP MSR stack.
895 * @returns @c true if it's part of LBR stack, @c false otherwise.
896 *
897 * @param pVM The cross context VM structure.
898 * @param idMsr The MSR.
899 * @param pidxMsr Where to store the index of the MSR in the LBR MSR array.
900 * Optional, can be NULL.
901 *
902 * @remarks Must only be called when LBR is enabled and when lastbranch-to-IP MSRs
903 * are supported by the CPU (see hmR0VmxSetupLbrMsrRange).
904 */
905DECL_FORCE_INLINE(bool) hmR0VmxIsLbrBranchToMsr(PCVM pVM, uint32_t idMsr, uint32_t *pidxMsr)
906{
907 Assert(pVM->hm.s.vmx.fLbr);
908 if (pVM->hm.s.vmx.idLbrToIpMsrFirst)
909 {
910 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrToIpMsrLast - pVM->hm.s.vmx.idLbrToIpMsrFirst + 1;
911 uint32_t const idxMsr = idMsr - pVM->hm.s.vmx.idLbrToIpMsrFirst;
912 if (idxMsr < cLbrStack)
913 {
914 if (pidxMsr)
915 *pidxMsr = idxMsr;
916 return true;
917 }
918 }
919 return false;
920}
921
922
923/**
924 * Gets the CR0 guest/host mask.
925 *
926 * These bits typically does not change through the lifetime of a VM. Any bit set in
927 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
928 * by the guest.
929 *
930 * @returns The CR0 guest/host mask.
931 * @param pVCpu The cross context virtual CPU structure.
932 */
933static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
934{
935 /*
936 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
937 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
938 *
939 * Furthermore, modifications to any bits that are reserved/unspecified currently
940 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
941 * when future CPUs specify and use currently reserved/unspecified bits.
942 */
943 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
944 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
945 * and @bugref{6944}. */
946 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
947 return ( X86_CR0_PE
948 | X86_CR0_NE
949 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
950 | X86_CR0_PG
951 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
952}
953
954
955/**
956 * Gets the CR4 guest/host mask.
957 *
958 * These bits typically does not change through the lifetime of a VM. Any bit set in
959 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
960 * by the guest.
961 *
962 * @returns The CR4 guest/host mask.
963 * @param pVCpu The cross context virtual CPU structure.
964 */
965static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
966{
967 /*
968 * We construct a mask of all CR4 bits that the guest can modify without causing
969 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
970 * a VM-exit when the guest attempts to modify them when executing using
971 * hardware-assisted VMX.
972 *
973 * When a feature is not exposed to the guest (and may be present on the host),
974 * we want to intercept guest modifications to the bit so we can emulate proper
975 * behavior (e.g., #GP).
976 *
977 * Furthermore, only modifications to those bits that don't require immediate
978 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
979 * depends on CR3 which might not always be the guest value while executing
980 * using hardware-assisted VMX.
981 */
982 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
983 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
984 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
985 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
986
987 /*
988 * Paranoia.
989 * Ensure features exposed to the guest are present on the host.
990 */
991 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
992 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
993 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
994
995 uint64_t const fGstMask = ( X86_CR4_PVI
996 | X86_CR4_TSD
997 | X86_CR4_DE
998 | X86_CR4_MCE
999 | X86_CR4_PCE
1000 | X86_CR4_OSXMMEEXCPT
1001 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
1002 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
1003 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
1004 return ~fGstMask;
1005}
1006
1007
1008/**
1009 * Gets the active (in use) VMCS info. object for the specified VCPU.
1010 *
1011 * This is either the guest or nested-guest VMCS info. and need not necessarily
1012 * pertain to the "current" VMCS (in the VMX definition of the term). For instance,
1013 * if the VM-entry failed due to an invalid-guest state, we may have "cleared" the
1014 * current VMCS while returning to ring-3. However, the VMCS info. object for that
1015 * VMCS would still be active and returned here so that we could dump the VMCS
1016 * fields to ring-3 for diagnostics. This function is thus only used to
1017 * distinguish between the nested-guest or guest VMCS.
1018 *
1019 * @returns The active VMCS information.
1020 * @param pVCpu The cross context virtual CPU structure.
1021 *
1022 * @thread EMT.
1023 * @remarks This function may be called with preemption or interrupts disabled!
1024 */
1025DECLINLINE(PVMXVMCSINFO) hmGetVmxActiveVmcsInfo(PVMCPUCC pVCpu)
1026{
1027 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
1028 return &pVCpu->hmr0.s.vmx.VmcsInfo;
1029 return &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1030}
1031
1032
1033/**
1034 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
1035 * area.
1036 *
1037 * @returns @c true if it's different, @c false otherwise.
1038 * @param pVmcsInfo The VMCS info. object.
1039 */
1040DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
1041{
1042 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
1043 && pVmcsInfo->pvGuestMsrStore);
1044}
1045
1046
1047/**
1048 * Sets the given Processor-based VM-execution controls.
1049 *
1050 * @param pVmxTransient The VMX-transient structure.
1051 * @param uProcCtls The Processor-based VM-execution controls to set.
1052 */
1053static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1054{
1055 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1056 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
1057 {
1058 pVmcsInfo->u32ProcCtls |= uProcCtls;
1059 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1060 AssertRC(rc);
1061 }
1062}
1063
1064
1065/**
1066 * Removes the given Processor-based VM-execution controls.
1067 *
1068 * @param pVCpu The cross context virtual CPU structure.
1069 * @param pVmxTransient The VMX-transient structure.
1070 * @param uProcCtls The Processor-based VM-execution controls to remove.
1071 *
1072 * @remarks When executing a nested-guest, this will not remove any of the specified
1073 * controls if the nested hypervisor has set any one of them.
1074 */
1075static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
1076{
1077 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1078 if (pVmcsInfo->u32ProcCtls & uProcCtls)
1079 {
1080#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1081 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
1082 ? true
1083 : !CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uProcCtls);
1084#else
1085 NOREF(pVCpu);
1086 bool const fRemoveCtls = true;
1087#endif
1088 if (fRemoveCtls)
1089 {
1090 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
1091 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
1092 AssertRC(rc);
1093 }
1094 }
1095}
1096
1097
1098/**
1099 * Sets the TSC offset for the current VMCS.
1100 *
1101 * @param uTscOffset The TSC offset to set.
1102 * @param pVmcsInfo The VMCS info. object.
1103 */
1104static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
1105{
1106 if (pVmcsInfo->u64TscOffset != uTscOffset)
1107 {
1108 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
1109 AssertRC(rc);
1110 pVmcsInfo->u64TscOffset = uTscOffset;
1111 }
1112}
1113
1114
1115/**
1116 * Adds one or more exceptions to the exception bitmap and commits it to the current
1117 * VMCS.
1118 *
1119 * @param pVmxTransient The VMX-transient structure.
1120 * @param uXcptMask The exception(s) to add.
1121 */
1122static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1123{
1124 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1125 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1126 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1127 {
1128 uXcptBitmap |= uXcptMask;
1129 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1130 AssertRC(rc);
1131 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1132 }
1133}
1134
1135
1136/**
1137 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1138 *
1139 * @param pVmxTransient The VMX-transient structure.
1140 * @param uXcpt The exception to add.
1141 */
1142static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1143{
1144 Assert(uXcpt <= X86_XCPT_LAST);
1145 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1146}
1147
1148
1149/**
1150 * Remove one or more exceptions from the exception bitmap and commits it to the
1151 * current VMCS.
1152 *
1153 * This takes care of not removing the exception intercept if a nested-guest
1154 * requires the exception to be intercepted.
1155 *
1156 * @returns VBox status code.
1157 * @param pVCpu The cross context virtual CPU structure.
1158 * @param pVmxTransient The VMX-transient structure.
1159 * @param uXcptMask The exception(s) to remove.
1160 */
1161static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1162{
1163 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1164 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1165 if (u32XcptBitmap & uXcptMask)
1166 {
1167#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1168 if (!pVmxTransient->fIsNestedGuest)
1169 { /* likely */ }
1170 else
1171 {
1172 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1173 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1174 }
1175#endif
1176#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1177 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1178 | RT_BIT(X86_XCPT_DE)
1179 | RT_BIT(X86_XCPT_NM)
1180 | RT_BIT(X86_XCPT_TS)
1181 | RT_BIT(X86_XCPT_UD)
1182 | RT_BIT(X86_XCPT_NP)
1183 | RT_BIT(X86_XCPT_SS)
1184 | RT_BIT(X86_XCPT_GP)
1185 | RT_BIT(X86_XCPT_PF)
1186 | RT_BIT(X86_XCPT_MF));
1187#elif defined(HMVMX_ALWAYS_TRAP_PF)
1188 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1189#endif
1190 if (uXcptMask)
1191 {
1192 /* Validate we are not removing any essential exception intercepts. */
1193 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1194 NOREF(pVCpu);
1195 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1196 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1197
1198 /* Remove it from the exception bitmap. */
1199 u32XcptBitmap &= ~uXcptMask;
1200
1201 /* Commit and update the cache if necessary. */
1202 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1203 {
1204 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1205 AssertRC(rc);
1206 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1207 }
1208 }
1209 }
1210 return VINF_SUCCESS;
1211}
1212
1213
1214/**
1215 * Remove an exceptions from the exception bitmap and commits it to the current
1216 * VMCS.
1217 *
1218 * @returns VBox status code.
1219 * @param pVCpu The cross context virtual CPU structure.
1220 * @param pVmxTransient The VMX-transient structure.
1221 * @param uXcpt The exception to remove.
1222 */
1223static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1224{
1225 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1226}
1227
1228
1229/**
1230 * Loads the VMCS specified by the VMCS info. object.
1231 *
1232 * @returns VBox status code.
1233 * @param pVmcsInfo The VMCS info. object.
1234 *
1235 * @remarks Can be called with interrupts disabled.
1236 */
1237static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1238{
1239 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1240 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1241
1242 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1243 if (RT_SUCCESS(rc))
1244 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1245 return rc;
1246}
1247
1248
1249/**
1250 * Clears the VMCS specified by the VMCS info. object.
1251 *
1252 * @returns VBox status code.
1253 * @param pVmcsInfo The VMCS info. object.
1254 *
1255 * @remarks Can be called with interrupts disabled.
1256 */
1257static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1258{
1259 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1261
1262 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1263 if (RT_SUCCESS(rc))
1264 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1265 return rc;
1266}
1267
1268
1269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1270/**
1271 * Loads the shadow VMCS specified by the VMCS info. object.
1272 *
1273 * @returns VBox status code.
1274 * @param pVmcsInfo The VMCS info. object.
1275 *
1276 * @remarks Can be called with interrupts disabled.
1277 */
1278static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1279{
1280 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1281 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1282
1283 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1284 if (RT_SUCCESS(rc))
1285 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1286 return rc;
1287}
1288
1289
1290/**
1291 * Clears the shadow VMCS specified by the VMCS info. object.
1292 *
1293 * @returns VBox status code.
1294 * @param pVmcsInfo The VMCS info. object.
1295 *
1296 * @remarks Can be called with interrupts disabled.
1297 */
1298static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1299{
1300 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1301 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1302
1303 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1304 if (RT_SUCCESS(rc))
1305 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1306 return rc;
1307}
1308
1309
1310/**
1311 * Switches from and to the specified VMCSes.
1312 *
1313 * @returns VBox status code.
1314 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1315 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1316 *
1317 * @remarks Called with interrupts disabled.
1318 */
1319static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1320{
1321 /*
1322 * Clear the VMCS we are switching out if it has not already been cleared.
1323 * This will sync any CPU internal data back to the VMCS.
1324 */
1325 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1326 {
1327 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1328 if (RT_SUCCESS(rc))
1329 {
1330 /*
1331 * The shadow VMCS, if any, would not be active at this point since we
1332 * would have cleared it while importing the virtual hardware-virtualization
1333 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1334 * clear the shadow VMCS here, just assert for safety.
1335 */
1336 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1337 }
1338 else
1339 return rc;
1340 }
1341
1342 /*
1343 * Clear the VMCS we are switching to if it has not already been cleared.
1344 * This will initialize the VMCS launch state to "clear" required for loading it.
1345 *
1346 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1347 */
1348 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1349 {
1350 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1351 if (RT_SUCCESS(rc))
1352 { /* likely */ }
1353 else
1354 return rc;
1355 }
1356
1357 /*
1358 * Finally, load the VMCS we are switching to.
1359 */
1360 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1361}
1362
1363
1364/**
1365 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1366 * caller.
1367 *
1368 * @returns VBox status code.
1369 * @param pVCpu The cross context virtual CPU structure.
1370 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1371 * true) or guest VMCS (pass false).
1372 */
1373static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1374{
1375 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1376 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1377
1378 PVMXVMCSINFO pVmcsInfoFrom;
1379 PVMXVMCSINFO pVmcsInfoTo;
1380 if (fSwitchToNstGstVmcs)
1381 {
1382 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfo;
1383 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1384 }
1385 else
1386 {
1387 pVmcsInfoFrom = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
1388 pVmcsInfoTo = &pVCpu->hmr0.s.vmx.VmcsInfo;
1389 }
1390
1391 /*
1392 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1393 * preemption hook code path acquires the current VMCS.
1394 */
1395 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1396
1397 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1398 if (RT_SUCCESS(rc))
1399 {
1400 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1401 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fSwitchToNstGstVmcs;
1402
1403 /*
1404 * If we are switching to a VMCS that was executed on a different host CPU or was
1405 * never executed before, flag that we need to export the host state before executing
1406 * guest/nested-guest code using hardware-assisted VMX.
1407 *
1408 * This could probably be done in a preemptible context since the preemption hook
1409 * will flag the necessary change in host context. However, since preemption is
1410 * already disabled and to avoid making assumptions about host specific code in
1411 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1412 * disabled.
1413 */
1414 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1415 { /* likely */ }
1416 else
1417 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1418
1419 ASMSetFlags(fEFlags);
1420
1421 /*
1422 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1423 * flag that we need to update the host MSR values there. Even if we decide in the
1424 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1425 * if its content differs, we would have to update the host MSRs anyway.
1426 */
1427 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
1428 }
1429 else
1430 ASMSetFlags(fEFlags);
1431 return rc;
1432}
1433#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1434
1435
1436/**
1437 * Updates the VM's last error record.
1438 *
1439 * If there was a VMX instruction error, reads the error data from the VMCS and
1440 * updates VCPU's last error record as well.
1441 *
1442 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1443 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1444 * VERR_VMX_INVALID_VMCS_FIELD.
1445 * @param rc The error code.
1446 */
1447static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1448{
1449 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1450 || rc == VERR_VMX_UNABLE_TO_START_VM)
1451 {
1452 AssertPtrReturnVoid(pVCpu);
1453 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1454 }
1455 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1456}
1457
1458
1459#ifdef VBOX_STRICT
1460/**
1461 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1462 * transient structure.
1463 *
1464 * @param pVmxTransient The VMX-transient structure.
1465 */
1466DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1467{
1468 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1469 AssertRC(rc);
1470}
1471
1472
1473/**
1474 * Reads the VM-entry exception error code field from the VMCS into
1475 * the VMX transient structure.
1476 *
1477 * @param pVmxTransient The VMX-transient structure.
1478 */
1479DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1480{
1481 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1482 AssertRC(rc);
1483}
1484
1485
1486/**
1487 * Reads the VM-entry exception error code field from the VMCS into
1488 * the VMX transient structure.
1489 *
1490 * @param pVmxTransient The VMX-transient structure.
1491 */
1492DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1493{
1494 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1495 AssertRC(rc);
1496}
1497#endif /* VBOX_STRICT */
1498
1499
1500/**
1501 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1502 * transient structure.
1503 *
1504 * @param pVmxTransient The VMX-transient structure.
1505 */
1506DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1507{
1508 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1509 {
1510 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1511 AssertRC(rc);
1512 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1513 }
1514}
1515
1516
1517/**
1518 * Reads the VM-exit interruption error code from the VMCS into the VMX
1519 * transient structure.
1520 *
1521 * @param pVmxTransient The VMX-transient structure.
1522 */
1523DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1524{
1525 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1526 {
1527 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1528 AssertRC(rc);
1529 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1530 }
1531}
1532
1533
1534/**
1535 * Reads the VM-exit instruction length field from the VMCS into the VMX
1536 * transient structure.
1537 *
1538 * @param pVmxTransient The VMX-transient structure.
1539 */
1540DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1541{
1542 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1543 {
1544 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1545 AssertRC(rc);
1546 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1547 }
1548}
1549
1550
1551/**
1552 * Reads the VM-exit instruction-information field from the VMCS into
1553 * the VMX transient structure.
1554 *
1555 * @param pVmxTransient The VMX-transient structure.
1556 */
1557DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1558{
1559 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1560 {
1561 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1562 AssertRC(rc);
1563 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1564 }
1565}
1566
1567
1568/**
1569 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1570 *
1571 * @param pVmxTransient The VMX-transient structure.
1572 */
1573DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1574{
1575 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1576 {
1577 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1578 AssertRC(rc);
1579 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1580 }
1581}
1582
1583
1584/**
1585 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1586 *
1587 * @param pVmxTransient The VMX-transient structure.
1588 */
1589DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1590{
1591 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1592 {
1593 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1594 AssertRC(rc);
1595 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1596 }
1597}
1598
1599
1600/**
1601 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1602 *
1603 * @param pVmxTransient The VMX-transient structure.
1604 */
1605DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1606{
1607 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1608 {
1609 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1610 AssertRC(rc);
1611 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1612 }
1613}
1614
1615#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1616/**
1617 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1618 * structure.
1619 *
1620 * @param pVmxTransient The VMX-transient structure.
1621 */
1622DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1623{
1624 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1625 {
1626 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1627 AssertRC(rc);
1628 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1629 }
1630}
1631#endif
1632
1633/**
1634 * Reads the IDT-vectoring information field from the VMCS into the VMX
1635 * transient structure.
1636 *
1637 * @param pVmxTransient The VMX-transient structure.
1638 *
1639 * @remarks No-long-jump zone!!!
1640 */
1641DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1642{
1643 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1644 {
1645 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1646 AssertRC(rc);
1647 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1648 }
1649}
1650
1651
1652/**
1653 * Reads the IDT-vectoring error code from the VMCS into the VMX
1654 * transient structure.
1655 *
1656 * @param pVmxTransient The VMX-transient structure.
1657 */
1658DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1659{
1660 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1661 {
1662 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1663 AssertRC(rc);
1664 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1665 }
1666}
1667
1668#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1669/**
1670 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1671 *
1672 * @param pVmxTransient The VMX-transient structure.
1673 */
1674static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1675{
1676 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1677 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1678 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1679 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1680 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1681 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1682 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1683 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1684 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1685 AssertRC(rc);
1686 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1687 | HMVMX_READ_EXIT_INSTR_LEN
1688 | HMVMX_READ_EXIT_INSTR_INFO
1689 | HMVMX_READ_IDT_VECTORING_INFO
1690 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1691 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1692 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1693 | HMVMX_READ_GUEST_LINEAR_ADDR
1694 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1695}
1696#endif
1697
1698/**
1699 * Enters VMX root mode operation on the current CPU.
1700 *
1701 * @returns VBox status code.
1702 * @param pHostCpu The HM physical-CPU structure.
1703 * @param pVM The cross context VM structure. Can be
1704 * NULL, after a resume.
1705 * @param HCPhysCpuPage Physical address of the VMXON region.
1706 * @param pvCpuPage Pointer to the VMXON region.
1707 */
1708static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1709{
1710 Assert(pHostCpu);
1711 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1712 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1713 Assert(pvCpuPage);
1714 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1715
1716 if (pVM)
1717 {
1718 /* Write the VMCS revision identifier to the VMXON region. */
1719 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1720 }
1721
1722 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1723 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1724
1725 /* Enable the VMX bit in CR4 if necessary. */
1726 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1727
1728 /* Record whether VMXE was already prior to us enabling it above. */
1729 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1730
1731 /* Enter VMX root mode. */
1732 int rc = VMXEnable(HCPhysCpuPage);
1733 if (RT_FAILURE(rc))
1734 {
1735 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1736 if (!pHostCpu->fVmxeAlreadyEnabled)
1737 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1738
1739 if (pVM)
1740 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1741 }
1742
1743 /* Restore interrupts. */
1744 ASMSetFlags(fEFlags);
1745 return rc;
1746}
1747
1748
1749/**
1750 * Exits VMX root mode operation on the current CPU.
1751 *
1752 * @returns VBox status code.
1753 * @param pHostCpu The HM physical-CPU structure.
1754 */
1755static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1756{
1757 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1758
1759 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1760 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1761
1762 /* If we're for some reason not in VMX root mode, then don't leave it. */
1763 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1764
1765 int rc;
1766 if (uHostCr4 & X86_CR4_VMXE)
1767 {
1768 /* Exit VMX root mode and clear the VMX bit in CR4. */
1769 VMXDisable();
1770
1771 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1772 if (!pHostCpu->fVmxeAlreadyEnabled)
1773 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1774
1775 rc = VINF_SUCCESS;
1776 }
1777 else
1778 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1779
1780 /* Restore interrupts. */
1781 ASMSetFlags(fEFlags);
1782 return rc;
1783}
1784
1785
1786/**
1787 * Allocates pages specified as specified by an array of VMX page allocation info
1788 * objects.
1789 *
1790 * The pages contents are zero'd after allocation.
1791 *
1792 * @returns VBox status code.
1793 * @param hMemObj The ring-0 memory object associated with the allocation.
1794 * @param paAllocInfo The pointer to the first element of the VMX
1795 * page-allocation info object array.
1796 * @param cEntries The number of elements in the @a paAllocInfo array.
1797 */
1798static int hmR0VmxPagesAllocZ(RTR0MEMOBJ hMemObj, PVMXPAGEALLOCINFO paAllocInfo, uint32_t cEntries)
1799{
1800 /* Figure out how many pages to allocate. */
1801 uint32_t cPages = 0;
1802 for (uint32_t iPage = 0; iPage < cEntries; iPage++)
1803 cPages += !!paAllocInfo[iPage].fValid;
1804
1805 /* Allocate the pages. */
1806 if (cPages)
1807 {
1808 size_t const cbPages = cPages << X86_PAGE_4K_SHIFT;
1809 int rc = RTR0MemObjAllocPage(&hMemObj, cbPages, false /* fExecutable */);
1810 if (RT_FAILURE(rc))
1811 return rc;
1812
1813 /* Zero the contents and assign each page to the corresponding VMX page-allocation entry. */
1814 void *pvFirstPage = RTR0MemObjAddress(hMemObj);
1815 ASMMemZero32(pvFirstPage, cbPages);
1816
1817 uint32_t iPage = 0;
1818 for (uint32_t i = 0; i < cEntries; i++)
1819 if (paAllocInfo[i].fValid)
1820 {
1821 RTHCPHYS const HCPhysPage = RTR0MemObjGetPagePhysAddr(hMemObj, iPage);
1822 void *pvPage = (void *)((uintptr_t)pvFirstPage + (iPage << X86_PAGE_4K_SHIFT));
1823 Assert(HCPhysPage && HCPhysPage != NIL_RTHCPHYS);
1824 AssertPtr(pvPage);
1825
1826 Assert(paAllocInfo[iPage].pHCPhys);
1827 Assert(paAllocInfo[iPage].ppVirt);
1828 *paAllocInfo[iPage].pHCPhys = HCPhysPage;
1829 *paAllocInfo[iPage].ppVirt = pvPage;
1830
1831 /* Move to next page. */
1832 ++iPage;
1833 }
1834
1835 /* Make sure all valid (requested) pages have been assigned. */
1836 Assert(iPage == cPages);
1837 }
1838 return VINF_SUCCESS;
1839}
1840
1841
1842/**
1843 * Frees pages allocated using hmR0VmxPagesAllocZ.
1844 *
1845 * @param hMemObj The ring-0 memory object associated with the allocation.
1846 */
1847DECL_FORCE_INLINE(void) hmR0VmxPagesFree(RTR0MEMOBJ hMemObj)
1848{
1849 /* We can cleanup wholesale since it's all one allocation. */
1850 RTR0MemObjFree(hMemObj, true /* fFreeMappings */);
1851}
1852
1853
1854/**
1855 * Initializes a VMCS info. object.
1856 *
1857 * @param pVmcsInfo The VMCS info. object.
1858 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1859 */
1860static void hmR0VmxVmcsInfoInit(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1861{
1862 RT_ZERO(*pVmcsInfo);
1863 RT_ZERO(*pVmcsInfoShared);
1864
1865 pVmcsInfo->pShared = pVmcsInfoShared;
1866 Assert(pVmcsInfo->hMemObj == NIL_RTR0MEMOBJ);
1867 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1868 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1869 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1870 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1871 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1872 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1873 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1874 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1875 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1876 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1877 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1878}
1879
1880
1881/**
1882 * Frees the VT-x structures for a VMCS info. object.
1883 *
1884 * @param pVmcsInfo The VMCS info. object.
1885 * @param pVmcsInfoShared The VMCS info. object shared with ring-3.
1886 */
1887static void hmR0VmxVmcsInfoFree(PVMXVMCSINFO pVmcsInfo, PVMXVMCSINFOSHARED pVmcsInfoShared)
1888{
1889 if (pVmcsInfo->hMemObj != NIL_RTR0MEMOBJ)
1890 {
1891 hmR0VmxPagesFree(pVmcsInfo->hMemObj);
1892 hmR0VmxVmcsInfoInit(pVmcsInfo, pVmcsInfoShared);
1893 }
1894}
1895
1896
1897/**
1898 * Allocates the VT-x structures for a VMCS info. object.
1899 *
1900 * @returns VBox status code.
1901 * @param pVCpu The cross context virtual CPU structure.
1902 * @param pVmcsInfo The VMCS info. object.
1903 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1904 *
1905 * @remarks The caller is expected to take care of any and all allocation failures.
1906 * This function will not perform any cleanup for failures half-way
1907 * through.
1908 */
1909static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1910{
1911 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1912
1913 bool const fMsrBitmaps = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS);
1914 bool const fShadowVmcs = !fIsNstGstVmcs ? pVM->hm.s.vmx.fUseVmcsShadowing : pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing;
1915 Assert(!pVM->cpum.ro.GuestFeatures.fVmxVmcsShadowing); /* VMCS shadowing is not yet exposed to the guest. */
1916 VMXPAGEALLOCINFO aAllocInfo[] = {
1917 { true, 0 /* Unused */, &pVmcsInfo->HCPhysVmcs, &pVmcsInfo->pvVmcs },
1918 { true, 0 /* Unused */, &pVmcsInfo->HCPhysGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad },
1919 { true, 0 /* Unused */, &pVmcsInfo->HCPhysHostMsrLoad, &pVmcsInfo->pvHostMsrLoad },
1920 { fMsrBitmaps, 0 /* Unused */, &pVmcsInfo->HCPhysMsrBitmap, &pVmcsInfo->pvMsrBitmap },
1921 { fShadowVmcs, 0 /* Unused */, &pVmcsInfo->HCPhysShadowVmcs, &pVmcsInfo->pvShadowVmcs },
1922 };
1923
1924 int rc = hmR0VmxPagesAllocZ(pVmcsInfo->hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
1925 if (RT_FAILURE(rc))
1926 return rc;
1927
1928 /*
1929 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1930 * Because they contain a symmetric list of guest MSRs to load on VM-entry and store on VM-exit.
1931 */
1932 AssertCompile(RT_ELEMENTS(aAllocInfo) > 0);
1933 Assert(pVmcsInfo->HCPhysGuestMsrLoad != NIL_RTHCPHYS);
1934 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1935 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1936
1937 /*
1938 * Get the virtual-APIC page rather than allocating them again.
1939 */
1940 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1941 {
1942 if (!fIsNstGstVmcs)
1943 {
1944 if (PDMHasApic(pVM))
1945 {
1946 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1947 if (RT_FAILURE(rc))
1948 return rc;
1949 Assert(pVmcsInfo->pbVirtApic);
1950 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1951 }
1952 }
1953 else
1954 {
1955 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(&pVCpu->cpum.GstCtx, &pVmcsInfo->HCPhysVirtApic);
1956 Assert(pVmcsInfo->pbVirtApic);
1957 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1958 }
1959 }
1960
1961 return VINF_SUCCESS;
1962}
1963
1964
1965/**
1966 * Free all VT-x structures for the VM.
1967 *
1968 * @returns IPRT status code.
1969 * @param pVM The cross context VM structure.
1970 */
1971static void hmR0VmxStructsFree(PVMCC pVM)
1972{
1973 hmR0VmxPagesFree(pVM->hm.s.vmx.hMemObj);
1974#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1975 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1976 {
1977 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1978 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1979 }
1980#endif
1981
1982 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1983 {
1984 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1985 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
1986#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1987 if (pVM->cpum.ro.GuestFeatures.fVmx)
1988 hmR0VmxVmcsInfoFree(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
1989#endif
1990 }
1991}
1992
1993
1994/**
1995 * Allocate all VT-x structures for the VM.
1996 *
1997 * @returns IPRT status code.
1998 * @param pVM The cross context VM structure.
1999 *
2000 * @remarks This functions will cleanup on memory allocation failures.
2001 */
2002static int hmR0VmxStructsAlloc(PVMCC pVM)
2003{
2004 /*
2005 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
2006 * The VMCS size cannot be more than 4096 bytes.
2007 *
2008 * See Intel spec. Appendix A.1 "Basic VMX Information".
2009 */
2010 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
2011 if (cbVmcs <= X86_PAGE_4K_SIZE)
2012 { /* likely */ }
2013 else
2014 {
2015 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
2016 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2017 }
2018
2019 /*
2020 * Allocate per-VM VT-x structures.
2021 */
2022 bool const fVirtApicAccess = RT_BOOL(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
2023 bool const fUseVmcsShadowing = pVM->hm.s.vmx.fUseVmcsShadowing;
2024 VMXPAGEALLOCINFO aAllocInfo[] = {
2025 { fVirtApicAccess, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess },
2026 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap },
2027 { fUseVmcsShadowing, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap },
2028#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2029 { true, 0 /* Unused */, &pVM->hm.s.vmx.HCPhysScratch, &(PRTR0PTR)pVM->hm.s.vmx.pbScratch },
2030#endif
2031 };
2032
2033 int rc = hmR0VmxPagesAllocZ(pVM->hm.s.vmx.hMemObj, &aAllocInfo[0], RT_ELEMENTS(aAllocInfo));
2034 if (RT_FAILURE(rc))
2035 goto cleanup;
2036
2037#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2038 /* Allocate the shadow VMCS-fields array. */
2039 if (fUseVmcsShadowing)
2040 {
2041 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
2042 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
2043 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2044 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2045 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
2046 && pVM->hm.s.vmx.paShadowVmcsRoFields))
2047 { /* likely */ }
2048 else
2049 {
2050 rc = VERR_NO_MEMORY;
2051 goto cleanup;
2052 }
2053 }
2054#endif
2055
2056 /*
2057 * Allocate per-VCPU VT-x structures.
2058 */
2059 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2060 {
2061 /* Allocate the guest VMCS structures. */
2062 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2063 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2064 if (RT_FAILURE(rc))
2065 goto cleanup;
2066
2067#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2068 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2069 if (pVM->cpum.ro.GuestFeatures.fVmx)
2070 {
2071 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2072 if (RT_FAILURE(rc))
2073 goto cleanup;
2074 }
2075#endif
2076 }
2077
2078 return VINF_SUCCESS;
2079
2080cleanup:
2081 hmR0VmxStructsFree(pVM);
2082 Assert(rc != VINF_SUCCESS);
2083 return rc;
2084}
2085
2086
2087/**
2088 * Pre-initializes non-zero fields in VMX structures that will be allocated.
2089 *
2090 * @param pVM The cross context VM structure.
2091 */
2092static void hmR0VmxStructsInit(PVMCC pVM)
2093{
2094 /* Paranoia. */
2095 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
2096#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2097 Assert(pVM->hm.s.vmx.pbScratch == NULL);
2098#endif
2099
2100 /*
2101 * Initialize members up-front so we can cleanup en masse on allocation failures.
2102 */
2103#ifdef VBOX_WITH_CRASHDUMP_MAGIC
2104 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
2105#endif
2106 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
2107 pVM->hm.s.vmx.HCPhysVmreadBitmap = NIL_RTHCPHYS;
2108 pVM->hm.s.vmx.HCPhysVmwriteBitmap = NIL_RTHCPHYS;
2109 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2110 {
2111 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2112 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfo, &pVCpu->hm.s.vmx.VmcsInfo);
2113 hmR0VmxVmcsInfoInit(&pVCpu->hmr0.s.vmx.VmcsInfoNstGst, &pVCpu->hm.s.vmx.VmcsInfoNstGst);
2114 }
2115}
2116
2117#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2118/**
2119 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2120 *
2121 * @returns @c true if the MSR is intercepted, @c false otherwise.
2122 * @param pvMsrBitmap The MSR bitmap.
2123 * @param offMsr The MSR byte offset.
2124 * @param iBit The bit offset from the byte offset.
2125 */
2126DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2127{
2128 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2129 Assert(pbMsrBitmap);
2130 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2131 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2132}
2133#endif
2134
2135/**
2136 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2137 *
2138 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2139 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2140 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2141 * the read/write access of this MSR.
2142 *
2143 * @param pVCpu The cross context virtual CPU structure.
2144 * @param pVmcsInfo The VMCS info. object.
2145 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2146 * @param idMsr The MSR value.
2147 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2148 * include both a read -and- a write permission!
2149 *
2150 * @sa CPUMGetVmxMsrPermission.
2151 * @remarks Can be called with interrupts disabled.
2152 */
2153static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2154{
2155 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2156 Assert(pbMsrBitmap);
2157 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2158
2159 /*
2160 * MSR-bitmap Layout:
2161 * Byte index MSR range Interpreted as
2162 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2163 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2164 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2165 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2166 *
2167 * A bit corresponding to an MSR within the above range causes a VM-exit
2168 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2169 * the MSR range, it always cause a VM-exit.
2170 *
2171 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2172 */
2173 uint16_t const offBitmapRead = 0;
2174 uint16_t const offBitmapWrite = 0x800;
2175 uint16_t offMsr;
2176 int32_t iBit;
2177 if (idMsr <= UINT32_C(0x00001fff))
2178 {
2179 offMsr = 0;
2180 iBit = idMsr;
2181 }
2182 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2183 {
2184 offMsr = 0x400;
2185 iBit = idMsr - UINT32_C(0xc0000000);
2186 }
2187 else
2188 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2189
2190 /*
2191 * Set the MSR read permission.
2192 */
2193 uint16_t const offMsrRead = offBitmapRead + offMsr;
2194 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2195 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2196 {
2197#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2198 bool const fClear = !fIsNstGstVmcs ? true
2199 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2200#else
2201 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2202 bool const fClear = true;
2203#endif
2204 if (fClear)
2205 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2206 }
2207 else
2208 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2209
2210 /*
2211 * Set the MSR write permission.
2212 */
2213 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2214 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2215 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2216 {
2217#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2218 bool const fClear = !fIsNstGstVmcs ? true
2219 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2220#else
2221 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2222 bool const fClear = true;
2223#endif
2224 if (fClear)
2225 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2226 }
2227 else
2228 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2229}
2230
2231
2232/**
2233 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2234 * area.
2235 *
2236 * @returns VBox status code.
2237 * @param pVCpu The cross context virtual CPU structure.
2238 * @param pVmcsInfo The VMCS info. object.
2239 * @param cMsrs The number of MSRs.
2240 */
2241static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2242{
2243 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2244 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2245 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2246 {
2247 /* Commit the MSR counts to the VMCS and update the cache. */
2248 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2249 {
2250 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2251 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2252 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2253 pVmcsInfo->cEntryMsrLoad = cMsrs;
2254 pVmcsInfo->cExitMsrStore = cMsrs;
2255 pVmcsInfo->cExitMsrLoad = cMsrs;
2256 }
2257 return VINF_SUCCESS;
2258 }
2259
2260 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2261 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2262 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2263}
2264
2265
2266/**
2267 * Adds a new (or updates the value of an existing) guest/host MSR
2268 * pair to be swapped during the world-switch as part of the
2269 * auto-load/store MSR area in the VMCS.
2270 *
2271 * @returns VBox status code.
2272 * @param pVCpu The cross context virtual CPU structure.
2273 * @param pVmxTransient The VMX-transient structure.
2274 * @param idMsr The MSR.
2275 * @param uGuestMsrValue Value of the guest MSR.
2276 * @param fSetReadWrite Whether to set the guest read/write access of this
2277 * MSR (thus not causing a VM-exit).
2278 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2279 * necessary.
2280 */
2281static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2282 bool fSetReadWrite, bool fUpdateHostMsr)
2283{
2284 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2285 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2286 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2287 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2288 uint32_t i;
2289
2290 /* Paranoia. */
2291 Assert(pGuestMsrLoad);
2292
2293 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGuestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2294
2295 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2296 for (i = 0; i < cMsrs; i++)
2297 {
2298 if (pGuestMsrLoad[i].u32Msr == idMsr)
2299 break;
2300 }
2301
2302 bool fAdded = false;
2303 if (i == cMsrs)
2304 {
2305 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2306 ++cMsrs;
2307 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2308 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2309
2310 /* Set the guest to read/write this MSR without causing VM-exits. */
2311 if ( fSetReadWrite
2312 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2313 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2314
2315 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2316 fAdded = true;
2317 }
2318
2319 /* Update the MSR value for the newly added or already existing MSR. */
2320 pGuestMsrLoad[i].u32Msr = idMsr;
2321 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2322
2323 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2324 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2325 {
2326 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2327 pGuestMsrStore[i].u32Msr = idMsr;
2328 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2329 }
2330
2331 /* Update the corresponding slot in the host MSR area. */
2332 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2333 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2334 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2335 pHostMsr[i].u32Msr = idMsr;
2336
2337 /*
2338 * Only if the caller requests to update the host MSR value AND we've newly added the
2339 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2340 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2341 *
2342 * We do this for performance reasons since reading MSRs may be quite expensive.
2343 */
2344 if (fAdded)
2345 {
2346 if (fUpdateHostMsr)
2347 {
2348 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2349 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2350 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2351 }
2352 else
2353 {
2354 /* Someone else can do the work. */
2355 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
2356 }
2357 }
2358 return VINF_SUCCESS;
2359}
2360
2361
2362/**
2363 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2364 * auto-load/store MSR area in the VMCS.
2365 *
2366 * @returns VBox status code.
2367 * @param pVCpu The cross context virtual CPU structure.
2368 * @param pVmxTransient The VMX-transient structure.
2369 * @param idMsr The MSR.
2370 */
2371static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2372{
2373 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2374 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2375 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2376 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2377
2378 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2379
2380 for (uint32_t i = 0; i < cMsrs; i++)
2381 {
2382 /* Find the MSR. */
2383 if (pGuestMsrLoad[i].u32Msr == idMsr)
2384 {
2385 /*
2386 * If it's the last MSR, we only need to reduce the MSR count.
2387 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2388 */
2389 if (i < cMsrs - 1)
2390 {
2391 /* Remove it from the VM-entry MSR-load area. */
2392 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2393 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2394
2395 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2396 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2397 {
2398 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2399 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2400 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2401 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2402 }
2403
2404 /* Remove it from the VM-exit MSR-load area. */
2405 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2406 Assert(pHostMsr[i].u32Msr == idMsr);
2407 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2408 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2409 }
2410
2411 /* Reduce the count to reflect the removed MSR and bail. */
2412 --cMsrs;
2413 break;
2414 }
2415 }
2416
2417 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2418 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2419 {
2420 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2421 AssertRCReturn(rc, rc);
2422
2423 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2424 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2425 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2426
2427 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2428 return VINF_SUCCESS;
2429 }
2430
2431 return VERR_NOT_FOUND;
2432}
2433
2434
2435/**
2436 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2437 *
2438 * @returns @c true if found, @c false otherwise.
2439 * @param pVmcsInfo The VMCS info. object.
2440 * @param idMsr The MSR to find.
2441 */
2442static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2443{
2444 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2445 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2446 Assert(pMsrs);
2447 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2448 for (uint32_t i = 0; i < cMsrs; i++)
2449 {
2450 if (pMsrs[i].u32Msr == idMsr)
2451 return true;
2452 }
2453 return false;
2454}
2455
2456
2457/**
2458 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2459 *
2460 * @param pVCpu The cross context virtual CPU structure.
2461 * @param pVmcsInfo The VMCS info. object.
2462 *
2463 * @remarks No-long-jump zone!!!
2464 */
2465static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2466{
2467 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2468
2469 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2470 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2471 Assert(pHostMsrLoad);
2472 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2473 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2474 for (uint32_t i = 0; i < cMsrs; i++)
2475 {
2476 /*
2477 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2478 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2479 */
2480 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2481 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2482 else
2483 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2484 }
2485}
2486
2487
2488/**
2489 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2490 * perform lazy restoration of the host MSRs while leaving VT-x.
2491 *
2492 * @param pVCpu The cross context virtual CPU structure.
2493 *
2494 * @remarks No-long-jump zone!!!
2495 */
2496static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2497{
2498 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2499
2500 /*
2501 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2502 */
2503 if (!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2504 {
2505 Assert(!(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2506 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2507 {
2508 pVCpu->hmr0.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2509 pVCpu->hmr0.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2510 pVCpu->hmr0.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2511 pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2512 }
2513 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2514 }
2515}
2516
2517
2518/**
2519 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2520 * lazily while leaving VT-x.
2521 *
2522 * @returns true if it does, false otherwise.
2523 * @param pVCpu The cross context virtual CPU structure.
2524 * @param idMsr The MSR to check.
2525 */
2526static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2527{
2528 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2529 {
2530 switch (idMsr)
2531 {
2532 case MSR_K8_LSTAR:
2533 case MSR_K6_STAR:
2534 case MSR_K8_SF_MASK:
2535 case MSR_K8_KERNEL_GS_BASE:
2536 return true;
2537 }
2538 }
2539 return false;
2540}
2541
2542
2543/**
2544 * Loads a set of guests MSRs to allow read/passthru to the guest.
2545 *
2546 * The name of this function is slightly confusing. This function does NOT
2547 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2548 * common prefix for functions dealing with "lazy restoration" of the shared
2549 * MSRs.
2550 *
2551 * @param pVCpu The cross context virtual CPU structure.
2552 *
2553 * @remarks No-long-jump zone!!!
2554 */
2555static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2556{
2557 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2558 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2559
2560 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2561 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2562 {
2563 /*
2564 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2565 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2566 * we can skip a few MSR writes.
2567 *
2568 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2569 * guest MSR values in the guest-CPU context might be different to what's currently
2570 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2571 * CPU, see @bugref{8728}.
2572 */
2573 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2574 if ( !(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2575 && pCtx->msrKERNELGSBASE == pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase
2576 && pCtx->msrLSTAR == pVCpu->hmr0.s.vmx.u64HostMsrLStar
2577 && pCtx->msrSTAR == pVCpu->hmr0.s.vmx.u64HostMsrStar
2578 && pCtx->msrSFMASK == pVCpu->hmr0.s.vmx.u64HostMsrSfMask)
2579 {
2580#ifdef VBOX_STRICT
2581 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2582 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2583 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2584 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2585#endif
2586 }
2587 else
2588 {
2589 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2590 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2591 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2592 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2593 }
2594 }
2595 pVCpu->hmr0.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2596}
2597
2598
2599/**
2600 * Performs lazy restoration of the set of host MSRs if they were previously
2601 * loaded with guest MSR values.
2602 *
2603 * @param pVCpu The cross context virtual CPU structure.
2604 *
2605 * @remarks No-long-jump zone!!!
2606 * @remarks The guest MSRs should have been saved back into the guest-CPU
2607 * context by hmR0VmxImportGuestState()!!!
2608 */
2609static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2610{
2611 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2612 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2613
2614 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2615 {
2616 Assert(pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2617 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2618 {
2619 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hmr0.s.vmx.u64HostMsrLStar);
2620 ASMWrMsr(MSR_K6_STAR, pVCpu->hmr0.s.vmx.u64HostMsrStar);
2621 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hmr0.s.vmx.u64HostMsrSfMask);
2622 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hmr0.s.vmx.u64HostMsrKernelGsBase);
2623 }
2624 }
2625 pVCpu->hmr0.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2626}
2627
2628
2629/**
2630 * Verifies that our cached values of the VMCS fields are all consistent with
2631 * what's actually present in the VMCS.
2632 *
2633 * @returns VBox status code.
2634 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2635 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2636 * VMCS content. HMCPU error-field is
2637 * updated, see VMX_VCI_XXX.
2638 * @param pVCpu The cross context virtual CPU structure.
2639 * @param pVmcsInfo The VMCS info. object.
2640 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2641 */
2642static int hmR0VmxCheckCachedVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2643{
2644 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2645
2646 uint32_t u32Val;
2647 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2648 AssertRC(rc);
2649 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2650 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2651 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2652 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2653
2654 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2655 AssertRC(rc);
2656 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2657 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2658 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2659 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2660
2661 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2662 AssertRC(rc);
2663 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2664 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2665 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2666 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2667
2668 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2669 AssertRC(rc);
2670 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2671 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2672 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2673 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2674
2675 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2676 {
2677 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2678 AssertRC(rc);
2679 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2680 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2681 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2682 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2683 }
2684
2685 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2686 AssertRC(rc);
2687 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2688 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2689 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2690 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2691
2692 uint64_t u64Val;
2693 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2694 AssertRC(rc);
2695 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2696 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2697 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2698 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2699
2700 NOREF(pcszVmcs);
2701 return VINF_SUCCESS;
2702}
2703
2704#ifdef VBOX_STRICT
2705
2706/**
2707 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2708 *
2709 * @param pVCpu The cross context virtual CPU structure.
2710 * @param pVmcsInfo The VMCS info. object.
2711 */
2712static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2713{
2714 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2715
2716 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2717 {
2718 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2719 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2720 uint64_t uVmcsEferMsrVmcs;
2721 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2722 AssertRC(rc);
2723
2724 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2725 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2726 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2727 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2728 }
2729}
2730
2731
2732/**
2733 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2734 * VMCS are correct.
2735 *
2736 * @param pVCpu The cross context virtual CPU structure.
2737 * @param pVmcsInfo The VMCS info. object.
2738 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2739 */
2740static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2741{
2742 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2743
2744 /* Read the various MSR-area counts from the VMCS. */
2745 uint32_t cEntryLoadMsrs;
2746 uint32_t cExitStoreMsrs;
2747 uint32_t cExitLoadMsrs;
2748 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2749 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2750 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2751
2752 /* Verify all the MSR counts are the same. */
2753 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2754 Assert(cExitStoreMsrs == cExitLoadMsrs);
2755 uint32_t const cMsrs = cExitLoadMsrs;
2756
2757 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2758 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2759
2760 /* Verify the MSR counts are within the allocated page size. */
2761 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2762
2763 /* Verify the relevant contents of the MSR areas match. */
2764 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2765 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2766 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2767 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2768 for (uint32_t i = 0; i < cMsrs; i++)
2769 {
2770 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2771 if (fSeparateExitMsrStorePage)
2772 {
2773 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2774 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2775 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2776 }
2777
2778 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2779 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2780 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2781
2782 uint64_t const u64HostMsr = ASMRdMsr(pHostMsrLoad->u32Msr);
2783 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64HostMsr,
2784 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2785 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64HostMsr, cMsrs));
2786
2787 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2788 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2789 if (fIsEferMsr)
2790 {
2791 AssertMsgReturnVoid(u64HostMsr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2792 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2793 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64HostMsr, cMsrs));
2794 }
2795
2796 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2797 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2798 {
2799 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2800 if (fIsEferMsr)
2801 {
2802 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2803 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2804 }
2805 else
2806 {
2807 /* Verify LBR MSRs (used only for debugging) are intercepted. We don't passthru these MSRs to the guest yet. */
2808 PCVM pVM = pVCpu->CTX_SUFF(pVM);
2809 if ( pVM->hm.s.vmx.fLbr
2810 && ( hmR0VmxIsLbrBranchFromMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2811 || hmR0VmxIsLbrBranchToMsr(pVM, pGuestMsrLoad->u32Msr, NULL /* pidxMsr */)
2812 || pGuestMsrLoad->u32Msr == pVM->hm.s.vmx.idLbrTosMsr))
2813 {
2814 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_EXIT_RD_WR,
2815 ("u32Msr=%#RX32 cMsrs=%u Passthru read/write for LBR MSRs!\n",
2816 pGuestMsrLoad->u32Msr, cMsrs));
2817 }
2818 else if (!fIsNstGstVmcs)
2819 {
2820 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_MASK) == VMXMSRPM_ALLOW_RD_WR,
2821 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2822 }
2823 else
2824 {
2825 /*
2826 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2827 * execute a nested-guest with MSR passthrough.
2828 *
2829 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2830 * allow passthrough too.
2831 */
2832 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2833 Assert(pvMsrBitmapNstGst);
2834 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2835 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2836 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2837 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2838 }
2839 }
2840 }
2841
2842 /* Move to the next MSR. */
2843 pHostMsrLoad++;
2844 pGuestMsrLoad++;
2845 pGuestMsrStore++;
2846 }
2847}
2848
2849#endif /* VBOX_STRICT */
2850
2851/**
2852 * Flushes the TLB using EPT.
2853 *
2854 * @returns VBox status code.
2855 * @param pVCpu The cross context virtual CPU structure of the calling
2856 * EMT. Can be NULL depending on @a enmTlbFlush.
2857 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2858 * enmTlbFlush.
2859 * @param enmTlbFlush Type of flush.
2860 *
2861 * @remarks Caller is responsible for making sure this function is called only
2862 * when NestedPaging is supported and providing @a enmTlbFlush that is
2863 * supported by the CPU.
2864 * @remarks Can be called with interrupts disabled.
2865 */
2866static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2867{
2868 uint64_t au64Descriptor[2];
2869 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2870 au64Descriptor[0] = 0;
2871 else
2872 {
2873 Assert(pVCpu);
2874 Assert(pVmcsInfo);
2875 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2876 }
2877 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2878
2879 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2880 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2881
2882 if ( RT_SUCCESS(rc)
2883 && pVCpu)
2884 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2885}
2886
2887
2888/**
2889 * Flushes the TLB using VPID.
2890 *
2891 * @returns VBox status code.
2892 * @param pVCpu The cross context virtual CPU structure of the calling
2893 * EMT. Can be NULL depending on @a enmTlbFlush.
2894 * @param enmTlbFlush Type of flush.
2895 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2896 * on @a enmTlbFlush).
2897 *
2898 * @remarks Can be called with interrupts disabled.
2899 */
2900static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2901{
2902 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2903
2904 uint64_t au64Descriptor[2];
2905 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2906 {
2907 au64Descriptor[0] = 0;
2908 au64Descriptor[1] = 0;
2909 }
2910 else
2911 {
2912 AssertPtr(pVCpu);
2913 AssertMsg(pVCpu->hmr0.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2914 AssertMsg(pVCpu->hmr0.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hmr0.s.uCurrentAsid));
2915 au64Descriptor[0] = pVCpu->hmr0.s.uCurrentAsid;
2916 au64Descriptor[1] = GCPtr;
2917 }
2918
2919 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2920 AssertMsg(rc == VINF_SUCCESS,
2921 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hmr0.s.uCurrentAsid : 0, GCPtr, rc));
2922
2923 if ( RT_SUCCESS(rc)
2924 && pVCpu)
2925 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2926 NOREF(rc);
2927}
2928
2929
2930/**
2931 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2932 * otherwise there is nothing really to invalidate.
2933 *
2934 * @returns VBox status code.
2935 * @param pVCpu The cross context virtual CPU structure.
2936 * @param GCVirt Guest virtual address of the page to invalidate.
2937 */
2938VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2939{
2940 AssertPtr(pVCpu);
2941 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2942
2943 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2944 {
2945 /*
2946 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2947 * the EPT case. See @bugref{6043} and @bugref{6177}.
2948 *
2949 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2950 * as this function maybe called in a loop with individual addresses.
2951 */
2952 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2953 if (pVM->hm.s.vmx.fVpid)
2954 {
2955 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2956 if (fVpidFlush)
2957 {
2958 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2959 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2960 }
2961 else
2962 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2963 }
2964 else if (pVM->hm.s.fNestedPaging)
2965 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2966 }
2967
2968 return VINF_SUCCESS;
2969}
2970
2971
2972/**
2973 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2974 * case where neither EPT nor VPID is supported by the CPU.
2975 *
2976 * @param pHostCpu The HM physical-CPU structure.
2977 * @param pVCpu The cross context virtual CPU structure.
2978 *
2979 * @remarks Called with interrupts disabled.
2980 */
2981static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2982{
2983 AssertPtr(pVCpu);
2984 AssertPtr(pHostCpu);
2985
2986 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2987
2988 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2989 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
2990 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2991 pVCpu->hmr0.s.fForceTLBFlush = false;
2992 return;
2993}
2994
2995
2996/**
2997 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2998 *
2999 * @param pHostCpu The HM physical-CPU structure.
3000 * @param pVCpu The cross context virtual CPU structure.
3001 * @param pVmcsInfo The VMCS info. object.
3002 *
3003 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
3004 * nomenclature. The reason is, to avoid confusion in compare statements
3005 * since the host-CPU copies are named "ASID".
3006 *
3007 * @remarks Called with interrupts disabled.
3008 */
3009static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3010{
3011#ifdef VBOX_WITH_STATISTICS
3012 bool fTlbFlushed = false;
3013# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
3014# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
3015 if (!fTlbFlushed) \
3016 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
3017 } while (0)
3018#else
3019# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
3020# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
3021#endif
3022
3023 AssertPtr(pVCpu);
3024 AssertPtr(pHostCpu);
3025 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3026
3027 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3028 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
3029 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
3030 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
3031
3032 /*
3033 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
3034 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3035 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3036 * cannot reuse the current ASID anymore.
3037 */
3038 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3039 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3040 {
3041 ++pHostCpu->uCurrentAsid;
3042 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3043 {
3044 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3045 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3046 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3047 }
3048
3049 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3050 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3051 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3052
3053 /*
3054 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3055 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3056 */
3057 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3058 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3059 HMVMX_SET_TAGGED_TLB_FLUSHED();
3060 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3061 }
3062 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3063 {
3064 /*
3065 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3066 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3067 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3068 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3069 * mappings, see @bugref{6568}.
3070 *
3071 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3072 */
3073 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3074 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3075 HMVMX_SET_TAGGED_TLB_FLUSHED();
3076 }
3077 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3078 {
3079 /*
3080 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3081 * address which requires flushing the TLB of EPT cached structures.
3082 *
3083 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3084 */
3085 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3086 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3087 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3088 HMVMX_SET_TAGGED_TLB_FLUSHED();
3089 }
3090
3091
3092 pVCpu->hmr0.s.fForceTLBFlush = false;
3093 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3094
3095 Assert(pVCpu->hmr0.s.idLastCpu == pHostCpu->idCpu);
3096 Assert(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3097 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3098 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3099 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3100 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3101 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3102 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3103 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3104
3105 /* Update VMCS with the VPID. */
3106 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3107 AssertRC(rc);
3108
3109#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3110}
3111
3112
3113/**
3114 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3115 *
3116 * @param pHostCpu The HM physical-CPU structure.
3117 * @param pVCpu The cross context virtual CPU structure.
3118 * @param pVmcsInfo The VMCS info. object.
3119 *
3120 * @remarks Called with interrupts disabled.
3121 */
3122static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3123{
3124 AssertPtr(pVCpu);
3125 AssertPtr(pHostCpu);
3126 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3127 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3128 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3129
3130 /*
3131 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3132 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3133 */
3134 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3135 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3136 {
3137 pVCpu->hmr0.s.fForceTLBFlush = true;
3138 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3139 }
3140
3141 /* Check for explicit TLB flushes. */
3142 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3143 {
3144 pVCpu->hmr0.s.fForceTLBFlush = true;
3145 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3146 }
3147
3148 /* Check for TLB flushes while switching to/from a nested-guest. */
3149 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3150 {
3151 pVCpu->hmr0.s.fForceTLBFlush = true;
3152 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3153 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3154 }
3155
3156 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3157 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3158
3159 if (pVCpu->hmr0.s.fForceTLBFlush)
3160 {
3161 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3162 pVCpu->hmr0.s.fForceTLBFlush = false;
3163 }
3164}
3165
3166
3167/**
3168 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3169 *
3170 * @param pHostCpu The HM physical-CPU structure.
3171 * @param pVCpu The cross context virtual CPU structure.
3172 *
3173 * @remarks Called with interrupts disabled.
3174 */
3175static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3176{
3177 AssertPtr(pVCpu);
3178 AssertPtr(pHostCpu);
3179 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3180 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3181 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3182
3183 /*
3184 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3185 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3186 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3187 * cannot reuse the current ASID anymore.
3188 */
3189 if ( pVCpu->hmr0.s.idLastCpu != pHostCpu->idCpu
3190 || pVCpu->hmr0.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3191 {
3192 pVCpu->hmr0.s.fForceTLBFlush = true;
3193 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3194 }
3195
3196 /* Check for explicit TLB flushes. */
3197 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3198 {
3199 /*
3200 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3201 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3202 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3203 * include fExplicitFlush's too) - an obscure corner case.
3204 */
3205 pVCpu->hmr0.s.fForceTLBFlush = true;
3206 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3207 }
3208
3209 /* Check for TLB flushes while switching to/from a nested-guest. */
3210 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3211 {
3212 pVCpu->hmr0.s.fForceTLBFlush = true;
3213 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3214 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3215 }
3216
3217 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3218 pVCpu->hmr0.s.idLastCpu = pHostCpu->idCpu;
3219 if (pVCpu->hmr0.s.fForceTLBFlush)
3220 {
3221 ++pHostCpu->uCurrentAsid;
3222 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3223 {
3224 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3225 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3226 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3227 }
3228
3229 pVCpu->hmr0.s.fForceTLBFlush = false;
3230 pVCpu->hmr0.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3231 pVCpu->hmr0.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3232 if (pHostCpu->fFlushAsidBeforeUse)
3233 {
3234 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3235 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3236 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3237 {
3238 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3239 pHostCpu->fFlushAsidBeforeUse = false;
3240 }
3241 else
3242 {
3243 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3244 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3245 }
3246 }
3247 }
3248
3249 AssertMsg(pVCpu->hmr0.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3250 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hmr0.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3251 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3252 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3253 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hmr0.s.idLastCpu, pVCpu->hmr0.s.cTlbFlushes));
3254 AssertMsg(pVCpu->hmr0.s.uCurrentAsid >= 1 && pVCpu->hmr0.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3255 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hmr0.s.uCurrentAsid));
3256
3257 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hmr0.s.uCurrentAsid);
3258 AssertRC(rc);
3259}
3260
3261
3262/**
3263 * Flushes the guest TLB entry based on CPU capabilities.
3264 *
3265 * @param pHostCpu The HM physical-CPU structure.
3266 * @param pVCpu The cross context virtual CPU structure.
3267 * @param pVmcsInfo The VMCS info. object.
3268 *
3269 * @remarks Called with interrupts disabled.
3270 */
3271static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3272{
3273#ifdef HMVMX_ALWAYS_FLUSH_TLB
3274 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3275#endif
3276 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3277 switch (pVM->hm.s.vmx.enmTlbFlushType)
3278 {
3279 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3280 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3281 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3282 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3283 default:
3284 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3285 break;
3286 }
3287 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3288}
3289
3290
3291/**
3292 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3293 * TLB entries from the host TLB before VM-entry.
3294 *
3295 * @returns VBox status code.
3296 * @param pVM The cross context VM structure.
3297 */
3298static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3299{
3300 /*
3301 * Determine optimal flush type for nested paging.
3302 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3303 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3304 */
3305 if (pVM->hm.s.fNestedPaging)
3306 {
3307 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3308 {
3309 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3310 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3311 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3312 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3313 else
3314 {
3315 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3316 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3317 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3318 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3319 }
3320
3321 /* Make sure the write-back cacheable memory type for EPT is supported. */
3322 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3323 {
3324 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3325 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3326 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3327 }
3328
3329 /* EPT requires a page-walk length of 4. */
3330 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3331 {
3332 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3333 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3334 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3335 }
3336 }
3337 else
3338 {
3339 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3340 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3341 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3342 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3343 }
3344 }
3345
3346 /*
3347 * Determine optimal flush type for VPID.
3348 */
3349 if (pVM->hm.s.vmx.fVpid)
3350 {
3351 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3352 {
3353 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3354 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3355 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3356 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3357 else
3358 {
3359 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3360 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3361 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3362 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3363 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3364 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3365 pVM->hm.s.vmx.fVpid = false;
3366 }
3367 }
3368 else
3369 {
3370 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3371 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3372 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3373 pVM->hm.s.vmx.fVpid = false;
3374 }
3375 }
3376
3377 /*
3378 * Setup the handler for flushing tagged-TLBs.
3379 */
3380 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3381 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3382 else if (pVM->hm.s.fNestedPaging)
3383 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3384 else if (pVM->hm.s.vmx.fVpid)
3385 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3386 else
3387 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3388 return VINF_SUCCESS;
3389}
3390
3391
3392/**
3393 * Sets up the LBR MSR ranges based on the host CPU.
3394 *
3395 * @returns VBox status code.
3396 * @param pVM The cross context VM structure.
3397 */
3398static int hmR0VmxSetupLbrMsrRange(PVMCC pVM)
3399{
3400 Assert(pVM->hm.s.vmx.fLbr);
3401 uint32_t idLbrFromIpMsrFirst;
3402 uint32_t idLbrFromIpMsrLast;
3403 uint32_t idLbrToIpMsrFirst;
3404 uint32_t idLbrToIpMsrLast;
3405 uint32_t idLbrTosMsr;
3406
3407 /*
3408 * Determine the LBR MSRs supported for this host CPU family and model.
3409 *
3410 * See Intel spec. 17.4.8 "LBR Stack".
3411 * See Intel "Model-Specific Registers" spec.
3412 */
3413 uint32_t const uFamilyModel = (pVM->cpum.ro.HostFeatures.uFamily << 8)
3414 | pVM->cpum.ro.HostFeatures.uModel;
3415 switch (uFamilyModel)
3416 {
3417 case 0x0f01: case 0x0f02:
3418 idLbrFromIpMsrFirst = MSR_P4_LASTBRANCH_0;
3419 idLbrFromIpMsrLast = MSR_P4_LASTBRANCH_3;
3420 idLbrToIpMsrFirst = 0x0;
3421 idLbrToIpMsrLast = 0x0;
3422 idLbrTosMsr = MSR_P4_LASTBRANCH_TOS;
3423 break;
3424
3425 case 0x065c: case 0x065f: case 0x064e: case 0x065e: case 0x068e:
3426 case 0x069e: case 0x0655: case 0x0666: case 0x067a: case 0x0667:
3427 case 0x066a: case 0x066c: case 0x067d: case 0x067e:
3428 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3429 idLbrFromIpMsrLast = MSR_LASTBRANCH_31_FROM_IP;
3430 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3431 idLbrToIpMsrLast = MSR_LASTBRANCH_31_TO_IP;
3432 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3433 break;
3434
3435 case 0x063d: case 0x0647: case 0x064f: case 0x0656: case 0x063c:
3436 case 0x0645: case 0x0646: case 0x063f: case 0x062a: case 0x062d:
3437 case 0x063a: case 0x063e: case 0x061a: case 0x061e: case 0x061f:
3438 case 0x062e: case 0x0625: case 0x062c: case 0x062f:
3439 idLbrFromIpMsrFirst = MSR_LASTBRANCH_0_FROM_IP;
3440 idLbrFromIpMsrLast = MSR_LASTBRANCH_15_FROM_IP;
3441 idLbrToIpMsrFirst = MSR_LASTBRANCH_0_TO_IP;
3442 idLbrToIpMsrLast = MSR_LASTBRANCH_15_TO_IP;
3443 idLbrTosMsr = MSR_LASTBRANCH_TOS;
3444 break;
3445
3446 case 0x0617: case 0x061d: case 0x060f:
3447 idLbrFromIpMsrFirst = MSR_CORE2_LASTBRANCH_0_FROM_IP;
3448 idLbrFromIpMsrLast = MSR_CORE2_LASTBRANCH_3_FROM_IP;
3449 idLbrToIpMsrFirst = MSR_CORE2_LASTBRANCH_0_TO_IP;
3450 idLbrToIpMsrLast = MSR_CORE2_LASTBRANCH_3_TO_IP;
3451 idLbrTosMsr = MSR_CORE2_LASTBRANCH_TOS;
3452 break;
3453
3454 /* Atom and related microarchitectures we don't care about:
3455 case 0x0637: case 0x064a: case 0x064c: case 0x064d: case 0x065a:
3456 case 0x065d: case 0x061c: case 0x0626: case 0x0627: case 0x0635:
3457 case 0x0636: */
3458 /* All other CPUs: */
3459 default:
3460 {
3461 LogRelFunc(("Could not determine LBR stack size for the CPU model %#x\n", uFamilyModel));
3462 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_UNKNOWN;
3463 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3464 }
3465 }
3466
3467 /*
3468 * Validate.
3469 */
3470 uint32_t const cLbrStack = idLbrFromIpMsrLast - idLbrFromIpMsrFirst + 1;
3471 PCVMCPU pVCpu0 = VMCC_GET_CPU_0(pVM);
3472 AssertCompile( RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr)
3473 == RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrToIpMsr));
3474 if (cLbrStack > RT_ELEMENTS(pVCpu0->hm.s.vmx.VmcsInfo.au64LbrFromIpMsr))
3475 {
3476 LogRelFunc(("LBR stack size of the CPU (%u) exceeds our buffer size\n", cLbrStack));
3477 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_LBR_STACK_SIZE_OVERFLOW;
3478 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3479 }
3480 NOREF(pVCpu0);
3481
3482 /*
3483 * Update the LBR info. to the VM struct. for use later.
3484 */
3485 pVM->hm.s.vmx.idLbrTosMsr = idLbrTosMsr;
3486 pVM->hm.s.vmx.idLbrFromIpMsrFirst = idLbrFromIpMsrFirst;
3487 pVM->hm.s.vmx.idLbrFromIpMsrLast = idLbrFromIpMsrLast;
3488
3489 pVM->hm.s.vmx.idLbrToIpMsrFirst = idLbrToIpMsrFirst;
3490 pVM->hm.s.vmx.idLbrToIpMsrLast = idLbrToIpMsrLast;
3491 return VINF_SUCCESS;
3492}
3493
3494
3495#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3496/**
3497 * Sets up the shadow VMCS fields arrays.
3498 *
3499 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3500 * executing the guest.
3501 *
3502 * @returns VBox status code.
3503 * @param pVM The cross context VM structure.
3504 */
3505static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3506{
3507 /*
3508 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3509 * when the host does not support it.
3510 */
3511 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3512 if ( !fGstVmwriteAll
3513 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3514 { /* likely. */ }
3515 else
3516 {
3517 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3518 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3519 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3520 }
3521
3522 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3523 uint32_t cRwFields = 0;
3524 uint32_t cRoFields = 0;
3525 for (uint32_t i = 0; i < cVmcsFields; i++)
3526 {
3527 VMXVMCSFIELD VmcsField;
3528 VmcsField.u = g_aVmcsFields[i];
3529
3530 /*
3531 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3532 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3533 * in the shadow VMCS fields array as they would be redundant.
3534 *
3535 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3536 * we must not include it in the shadow VMCS fields array. Guests attempting to
3537 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3538 * the required behavior.
3539 */
3540 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3541 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3542 {
3543 /*
3544 * Read-only fields are placed in a separate array so that while syncing shadow
3545 * VMCS fields later (which is more performance critical) we can avoid branches.
3546 *
3547 * However, if the guest can write to all fields (including read-only fields),
3548 * we treat it a as read/write field. Otherwise, writing to these fields would
3549 * cause a VMWRITE instruction error while syncing the shadow VMCS.
3550 */
3551 if ( fGstVmwriteAll
3552 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3553 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3554 else
3555 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3556 }
3557 }
3558
3559 /* Update the counts. */
3560 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3561 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3562 return VINF_SUCCESS;
3563}
3564
3565
3566/**
3567 * Sets up the VMREAD and VMWRITE bitmaps.
3568 *
3569 * @param pVM The cross context VM structure.
3570 */
3571static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3572{
3573 /*
3574 * By default, ensure guest attempts to access any VMCS fields cause VM-exits.
3575 */
3576 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3577 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3578 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3579 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3580 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3581
3582 /*
3583 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3584 * VMREAD and VMWRITE bitmaps.
3585 */
3586 {
3587 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3588 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3589 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3590 {
3591 uint32_t const uVmcsField = paShadowVmcsFields[i];
3592 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3593 Assert(uVmcsField >> 3 < cbBitmap);
3594 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3595 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3596 }
3597 }
3598
3599 /*
3600 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3601 * if the host supports VMWRITE to all supported VMCS fields.
3602 */
3603 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3604 {
3605 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3606 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3607 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3608 {
3609 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3610 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3611 Assert(uVmcsField >> 3 < cbBitmap);
3612 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3613 }
3614 }
3615}
3616#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3617
3618
3619/**
3620 * Sets up the virtual-APIC page address for the VMCS.
3621 *
3622 * @param pVmcsInfo The VMCS info. object.
3623 */
3624DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3625{
3626 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3627 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3628 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3629 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3630 AssertRC(rc);
3631}
3632
3633
3634/**
3635 * Sets up the MSR-bitmap address for the VMCS.
3636 *
3637 * @param pVmcsInfo The VMCS info. object.
3638 */
3639DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3640{
3641 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3642 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3643 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3644 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3645 AssertRC(rc);
3646}
3647
3648
3649/**
3650 * Sets up the APIC-access page address for the VMCS.
3651 *
3652 * @param pVCpu The cross context virtual CPU structure.
3653 */
3654DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3655{
3656 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3657 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3658 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3659 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3660 AssertRC(rc);
3661}
3662
3663
3664#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3665/**
3666 * Sets up the VMREAD bitmap address for the VMCS.
3667 *
3668 * @param pVCpu The cross context virtual CPU structure.
3669 */
3670DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3671{
3672 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3673 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3674 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3675 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3676 AssertRC(rc);
3677}
3678
3679
3680/**
3681 * Sets up the VMWRITE bitmap address for the VMCS.
3682 *
3683 * @param pVCpu The cross context virtual CPU structure.
3684 */
3685DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3686{
3687 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3688 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3689 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3690 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3691 AssertRC(rc);
3692}
3693#endif
3694
3695
3696/**
3697 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3698 * in the VMCS.
3699 *
3700 * @returns VBox status code.
3701 * @param pVmcsInfo The VMCS info. object.
3702 */
3703DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3704{
3705 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3706 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3707 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3708
3709 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3710 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3711 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3712
3713 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3714 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3715 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3716
3717 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3718 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3719 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3720 return VINF_SUCCESS;
3721}
3722
3723
3724/**
3725 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3726 *
3727 * @param pVCpu The cross context virtual CPU structure.
3728 * @param pVmcsInfo The VMCS info. object.
3729 */
3730static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3731{
3732 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3733
3734 /*
3735 * By default, ensure guest attempts to access any MSR cause VM-exits.
3736 * This shall later be relaxed for specific MSRs as necessary.
3737 *
3738 * Note: For nested-guests, the entire bitmap will be merged prior to
3739 * executing the nested-guest using hardware-assisted VMX and hence there
3740 * is no need to perform this operation. See hmR0VmxMergeMsrBitmapNested.
3741 */
3742 Assert(pVmcsInfo->pvMsrBitmap);
3743 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
3744
3745 /*
3746 * The guest can access the following MSRs (read, write) without causing
3747 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3748 */
3749 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3750 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3751 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3752 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3753 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3754 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3755
3756 /*
3757 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3758 * associated with then. We never need to intercept access (writes need to be
3759 * executed without causing a VM-exit, reads will #GP fault anyway).
3760 *
3761 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3762 * read/write them. We swap the the guest/host MSR value using the
3763 * auto-load/store MSR area.
3764 */
3765 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3766 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3767 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3768 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3769 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3770 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3771
3772 /*
3773 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3774 * required for 64-bit guests.
3775 */
3776 if (pVM->hm.s.fAllow64BitGuests)
3777 {
3778 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3779 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3780 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3781 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3782 }
3783
3784 /*
3785 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3786 */
3787#ifdef VBOX_STRICT
3788 Assert(pVmcsInfo->pvMsrBitmap);
3789 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3790 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3791#endif
3792}
3793
3794
3795/**
3796 * Sets up pin-based VM-execution controls in the VMCS.
3797 *
3798 * @returns VBox status code.
3799 * @param pVCpu The cross context virtual CPU structure.
3800 * @param pVmcsInfo The VMCS info. object.
3801 */
3802static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3803{
3804 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3805 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3806 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3807
3808 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3809 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3810
3811 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3812 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3813
3814 /* Enable the VMX-preemption timer. */
3815 if (pVM->hm.s.vmx.fUsePreemptTimer)
3816 {
3817 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3818 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3819 }
3820
3821#if 0
3822 /* Enable posted-interrupt processing. */
3823 if (pVM->hm.s.fPostedIntrs)
3824 {
3825 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3826 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3827 fVal |= VMX_PIN_CTLS_POSTED_INT;
3828 }
3829#endif
3830
3831 if ((fVal & fZap) != fVal)
3832 {
3833 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3834 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3835 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3836 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3837 }
3838
3839 /* Commit it to the VMCS and update our cache. */
3840 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3841 AssertRC(rc);
3842 pVmcsInfo->u32PinCtls = fVal;
3843
3844 return VINF_SUCCESS;
3845}
3846
3847
3848/**
3849 * Sets up secondary processor-based VM-execution controls in the VMCS.
3850 *
3851 * @returns VBox status code.
3852 * @param pVCpu The cross context virtual CPU structure.
3853 * @param pVmcsInfo The VMCS info. object.
3854 */
3855static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3856{
3857 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3858 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3859 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3860
3861 /* WBINVD causes a VM-exit. */
3862 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3863 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3864
3865 /* Enable EPT (aka nested-paging). */
3866 if (pVM->hm.s.fNestedPaging)
3867 fVal |= VMX_PROC_CTLS2_EPT;
3868
3869 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3870 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3871 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3872 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3873 fVal |= VMX_PROC_CTLS2_INVPCID;
3874
3875 /* Enable VPID. */
3876 if (pVM->hm.s.vmx.fVpid)
3877 fVal |= VMX_PROC_CTLS2_VPID;
3878
3879 /* Enable unrestricted guest execution. */
3880 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3881 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3882
3883#if 0
3884 if (pVM->hm.s.fVirtApicRegs)
3885 {
3886 /* Enable APIC-register virtualization. */
3887 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3888 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3889
3890 /* Enable virtual-interrupt delivery. */
3891 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3892 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3893 }
3894#endif
3895
3896 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3897 where the TPR shadow resides. */
3898 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3899 * done dynamically. */
3900 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3901 {
3902 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3903 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3904 }
3905
3906 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3907 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3908 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3909 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3910 fVal |= VMX_PROC_CTLS2_RDTSCP;
3911
3912 /* Enable Pause-Loop exiting. */
3913 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3914 && pVM->hm.s.vmx.cPleGapTicks
3915 && pVM->hm.s.vmx.cPleWindowTicks)
3916 {
3917 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3918
3919 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3920 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3921 }
3922
3923 if ((fVal & fZap) != fVal)
3924 {
3925 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3926 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3927 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3928 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3929 }
3930
3931 /* Commit it to the VMCS and update our cache. */
3932 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3933 AssertRC(rc);
3934 pVmcsInfo->u32ProcCtls2 = fVal;
3935
3936 return VINF_SUCCESS;
3937}
3938
3939
3940/**
3941 * Sets up processor-based VM-execution controls in the VMCS.
3942 *
3943 * @returns VBox status code.
3944 * @param pVCpu The cross context virtual CPU structure.
3945 * @param pVmcsInfo The VMCS info. object.
3946 */
3947static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3948{
3949 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3950 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3951 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3952
3953 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3954 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3955 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3956 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3957 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3958 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3959 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3960
3961 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3962 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3963 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3964 {
3965 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3966 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3967 }
3968
3969 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3970 if (!pVM->hm.s.fNestedPaging)
3971 {
3972 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3973 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3974 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3975 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3976 }
3977
3978 /* Use TPR shadowing if supported by the CPU. */
3979 if ( PDMHasApic(pVM)
3980 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
3981 {
3982 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3983 /* CR8 writes cause a VM-exit based on TPR threshold. */
3984 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3985 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3986 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3987 }
3988 else
3989 {
3990 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3991 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3992 if (pVM->hm.s.fAllow64BitGuests)
3993 {
3994 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3995 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3996 }
3997 }
3998
3999 /* Use MSR-bitmaps if supported by the CPU. */
4000 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4001 {
4002 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
4003 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4004 }
4005
4006 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
4007 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4008 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
4009
4010 if ((fVal & fZap) != fVal)
4011 {
4012 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4013 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
4014 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
4015 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4016 }
4017
4018 /* Commit it to the VMCS and update our cache. */
4019 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
4020 AssertRC(rc);
4021 pVmcsInfo->u32ProcCtls = fVal;
4022
4023 /* Set up MSR permissions that don't change through the lifetime of the VM. */
4024 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4025 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
4026
4027 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
4028 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
4029 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
4030
4031 /* Sanity check, should not really happen. */
4032 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
4033 { /* likely */ }
4034 else
4035 {
4036 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
4037 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4038 }
4039
4040 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
4041 return VINF_SUCCESS;
4042}
4043
4044
4045/**
4046 * Sets up miscellaneous (everything other than Pin, Processor and secondary
4047 * Processor-based VM-execution) control fields in the VMCS.
4048 *
4049 * @returns VBox status code.
4050 * @param pVCpu The cross context virtual CPU structure.
4051 * @param pVmcsInfo The VMCS info. object.
4052 */
4053static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4054{
4055#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4056 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
4057 {
4058 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
4059 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
4060 }
4061#endif
4062
4063 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4064 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4065 AssertRC(rc);
4066
4067 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4068 if (RT_SUCCESS(rc))
4069 {
4070 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
4071 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
4072
4073 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
4074 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
4075
4076 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
4077 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
4078
4079 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fLbr)
4080 {
4081 rc = VMXWriteVmcsNw(VMX_VMCS64_GUEST_DEBUGCTL_FULL, MSR_IA32_DEBUGCTL_LBR);
4082 AssertRC(rc);
4083 }
4084 return VINF_SUCCESS;
4085 }
4086 else
4087 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
4088 return rc;
4089}
4090
4091
4092/**
4093 * Sets up the initial exception bitmap in the VMCS based on static conditions.
4094 *
4095 * We shall setup those exception intercepts that don't change during the
4096 * lifetime of the VM here. The rest are done dynamically while loading the
4097 * guest state.
4098 *
4099 * @param pVCpu The cross context virtual CPU structure.
4100 * @param pVmcsInfo The VMCS info. object.
4101 */
4102static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4103{
4104 /*
4105 * The following exceptions are always intercepted:
4106 *
4107 * #AC - To prevent the guest from hanging the CPU.
4108 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
4109 * recursive #DBs can cause a CPU hang.
4110 * #PF - To sync our shadow page tables when nested-paging is not used.
4111 */
4112 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
4113 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
4114 | RT_BIT(X86_XCPT_DB)
4115 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
4116
4117 /* Commit it to the VMCS. */
4118 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
4119 AssertRC(rc);
4120
4121 /* Update our cache of the exception bitmap. */
4122 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
4123}
4124
4125
4126#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4127/**
4128 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
4129 *
4130 * @returns VBox status code.
4131 * @param pVCpu The cross context virtual CPU structure.
4132 * @param pVmcsInfo The VMCS info. object.
4133 */
4134static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
4135{
4136 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4137 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4138 AssertRC(rc);
4139
4140 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
4141 if (RT_SUCCESS(rc))
4142 {
4143 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4144 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
4145
4146 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
4147 Assert(!pVmcsInfo->u64Cr0Mask);
4148 Assert(!pVmcsInfo->u64Cr4Mask);
4149 return VINF_SUCCESS;
4150 }
4151 else
4152 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4153 return rc;
4154}
4155#endif
4156
4157
4158/**
4159 * Sets pfnStartVm to the best suited variant.
4160 *
4161 * This must be called whenever anything changes relative to the hmR0VmXStartVm
4162 * variant selection:
4163 * - pVCpu->hm.s.fLoadSaveGuestXcr0
4164 * - CPUMCTX_WSF_IBPB_ENTRY in pVCpu->cpum.GstCtx.fWorldSwitcher
4165 * - CPUMCTX_WSF_IBPB_EXIT in pVCpu->cpum.GstCtx.fWorldSwitcher
4166 * - Perhaps: CPUMIsGuestFPUStateActive() (windows only)
4167 * - Perhaps: CPUMCTX.fXStateMask (windows only)
4168 *
4169 * We currently ASSUME that neither CPUMCTX_WSF_IBPB_ENTRY nor
4170 * CPUMCTX_WSF_IBPB_EXIT cannot be changed at runtime.
4171 */
4172static void hmR0VmxUpdateStartVmFunction(PVMCPUCC pVCpu)
4173{
4174 static const struct CLANGWORKAROUND { PFNHMVMXSTARTVM pfn; } s_aHmR0VmxStartVmFunctions[] =
4175 {
4176 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4177 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4178 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4179 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_SansIbpbExit },
4180 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4181 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4182 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4183 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_SansIbpbExit },
4184 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4185 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4186 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4187 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_SansIbpbExit },
4188 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4189 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4190 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4191 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_SansIbpbExit },
4192 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4193 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4194 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4195 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_SansMdsEntry_WithIbpbExit },
4196 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4197 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4198 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4199 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_SansMdsEntry_WithIbpbExit },
4200 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4201 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4202 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4203 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_SansL1dEntry_WithMdsEntry_WithIbpbExit },
4204 { hmR0VmxStartVm_SansXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4205 { hmR0VmxStartVm_WithXcr0_SansIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4206 { hmR0VmxStartVm_SansXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4207 { hmR0VmxStartVm_WithXcr0_WithIbpbEntry_WithL1dEntry_WithMdsEntry_WithIbpbExit },
4208 };
4209 uintptr_t const idx = (pVCpu->hmr0.s.fLoadSaveGuestXcr0 ? 1 : 0)
4210 | (pVCpu->cpum.GstCtx.fWorldSwitcher & CPUMCTX_WSF_IBPB_ENTRY ? 2 : 0)
4211 | (pVCpu->cpum.GstCtx.fWorldSwitcher & CPUMCTX_WSF_L1D_ENTRY ? 4 : 0)
4212 | (pVCpu->cpum.GstCtx.fWorldSwitcher & CPUMCTX_WSF_MDS_ENTRY ? 8 : 0)
4213 | (pVCpu->cpum.GstCtx.fWorldSwitcher & CPUMCTX_WSF_IBPB_EXIT ? 16 : 0);
4214 PFNHMVMXSTARTVM const pfnStartVm = s_aHmR0VmxStartVmFunctions[idx].pfn;
4215 if (pVCpu->hmr0.s.vmx.pfnStartVm != pfnStartVm)
4216 pVCpu->hmr0.s.vmx.pfnStartVm = pfnStartVm;
4217}
4218
4219
4220/**
4221 * Selector FNHMSVMVMRUN implementation.
4222 */
4223static DECLCALLBACK(int) hmR0VmxStartVmSelector(PVMXVMCSINFO pVmcsInfo, PVMCPUCC pVCpu, bool fResume)
4224{
4225 hmR0VmxUpdateStartVmFunction(pVCpu);
4226 return pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResume);
4227}
4228
4229
4230/**
4231 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4232 * VMX.
4233 *
4234 * @returns VBox status code.
4235 * @param pVCpu The cross context virtual CPU structure.
4236 * @param pVmcsInfo The VMCS info. object.
4237 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4238 */
4239static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4240{
4241 Assert(pVmcsInfo->pvVmcs);
4242 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4243
4244 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4245 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4246 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4247 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4248
4249 LogFlowFunc(("\n"));
4250
4251 /*
4252 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4253 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4254 */
4255 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4256 if (RT_SUCCESS(rc))
4257 {
4258 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4259 if (RT_SUCCESS(rc))
4260 {
4261 /*
4262 * Initialize the hardware-assisted VMX execution handler for guest and nested-guest VMCS.
4263 * The host is always 64-bit since we no longer support 32-bit hosts.
4264 * Currently we have just a single handler for all guest modes as well, see @bugref{6208#c73}.
4265 */
4266 if (!fIsNstGstVmcs)
4267 {
4268 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4269 if (RT_SUCCESS(rc))
4270 {
4271 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4272 if (RT_SUCCESS(rc))
4273 {
4274 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4275 if (RT_SUCCESS(rc))
4276 {
4277 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4278#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4279 /*
4280 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4281 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4282 * making it fit for use when VMCS shadowing is later enabled.
4283 */
4284 if (pVmcsInfo->pvShadowVmcs)
4285 {
4286 VMXVMCSREVID VmcsRevId;
4287 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4288 VmcsRevId.n.fIsShadowVmcs = 1;
4289 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4290 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4291 if (RT_SUCCESS(rc))
4292 { /* likely */ }
4293 else
4294 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4295 }
4296#endif
4297 }
4298 else
4299 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4300 }
4301 else
4302 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4303 }
4304 else
4305 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4306 }
4307 else
4308 {
4309#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4310 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4311 if (RT_SUCCESS(rc))
4312 { /* likely */ }
4313 else
4314 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4315#else
4316 AssertFailed();
4317#endif
4318 }
4319 }
4320 else
4321 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4322 }
4323 else
4324 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4325
4326 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4327 if (RT_SUCCESS(rc))
4328 {
4329 rc = hmR0VmxClearVmcs(pVmcsInfo);
4330 if (RT_SUCCESS(rc))
4331 { /* likely */ }
4332 else
4333 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4334 }
4335
4336 /*
4337 * Update the last-error record both for failures and success, so we
4338 * can propagate the status code back to ring-3 for diagnostics.
4339 */
4340 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4341 NOREF(pszVmcs);
4342 return rc;
4343}
4344
4345
4346/**
4347 * Does global VT-x initialization (called during module initialization).
4348 *
4349 * @returns VBox status code.
4350 */
4351VMMR0DECL(int) VMXR0GlobalInit(void)
4352{
4353#ifdef HMVMX_USE_FUNCTION_TABLE
4354 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_aVMExitHandlers));
4355# ifdef VBOX_STRICT
4356 for (unsigned i = 0; i < RT_ELEMENTS(g_aVMExitHandlers); i++)
4357 Assert(g_aVMExitHandlers[i].pfn);
4358# endif
4359#endif
4360 return VINF_SUCCESS;
4361}
4362
4363
4364/**
4365 * Does global VT-x termination (called during module termination).
4366 */
4367VMMR0DECL(void) VMXR0GlobalTerm()
4368{
4369 /* Nothing to do currently. */
4370}
4371
4372
4373/**
4374 * Sets up and activates VT-x on the current CPU.
4375 *
4376 * @returns VBox status code.
4377 * @param pHostCpu The HM physical-CPU structure.
4378 * @param pVM The cross context VM structure. Can be
4379 * NULL after a host resume operation.
4380 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4381 * fEnabledByHost is @c true).
4382 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4383 * @a fEnabledByHost is @c true).
4384 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4385 * enable VT-x on the host.
4386 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4387 */
4388VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4389 PCSUPHWVIRTMSRS pHwvirtMsrs)
4390{
4391 AssertPtr(pHostCpu);
4392 AssertPtr(pHwvirtMsrs);
4393 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4394
4395 /* Enable VT-x if it's not already enabled by the host. */
4396 if (!fEnabledByHost)
4397 {
4398 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4399 if (RT_FAILURE(rc))
4400 return rc;
4401 }
4402
4403 /*
4404 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4405 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4406 * invalidated when flushing by VPID.
4407 */
4408 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4409 {
4410 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4411 pHostCpu->fFlushAsidBeforeUse = false;
4412 }
4413 else
4414 pHostCpu->fFlushAsidBeforeUse = true;
4415
4416 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4417 ++pHostCpu->cTlbFlushes;
4418
4419 return VINF_SUCCESS;
4420}
4421
4422
4423/**
4424 * Deactivates VT-x on the current CPU.
4425 *
4426 * @returns VBox status code.
4427 * @param pHostCpu The HM physical-CPU structure.
4428 * @param pvCpuPage Pointer to the VMXON region.
4429 * @param HCPhysCpuPage Physical address of the VMXON region.
4430 *
4431 * @remarks This function should never be called when SUPR0EnableVTx() or
4432 * similar was used to enable VT-x on the host.
4433 */
4434VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4435{
4436 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4437
4438 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4439 return hmR0VmxLeaveRootMode(pHostCpu);
4440}
4441
4442
4443/**
4444 * Does per-VM VT-x initialization.
4445 *
4446 * @returns VBox status code.
4447 * @param pVM The cross context VM structure.
4448 */
4449VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4450{
4451 AssertPtr(pVM);
4452 LogFlowFunc(("pVM=%p\n", pVM));
4453
4454 hmR0VmxStructsInit(pVM);
4455 int rc = hmR0VmxStructsAlloc(pVM);
4456 if (RT_FAILURE(rc))
4457 {
4458 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4459 return rc;
4460 }
4461
4462 /* Setup the crash dump page. */
4463#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4464 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
4465 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
4466#endif
4467 return VINF_SUCCESS;
4468}
4469
4470
4471/**
4472 * Does per-VM VT-x termination.
4473 *
4474 * @returns VBox status code.
4475 * @param pVM The cross context VM structure.
4476 */
4477VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4478{
4479 AssertPtr(pVM);
4480 LogFlowFunc(("pVM=%p\n", pVM));
4481
4482#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4483 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4484 {
4485 Assert(pVM->hm.s.vmx.pvScratch);
4486 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4487 }
4488#endif
4489 hmR0VmxStructsFree(pVM);
4490 return VINF_SUCCESS;
4491}
4492
4493
4494/**
4495 * Sets up the VM for execution using hardware-assisted VMX.
4496 * This function is only called once per-VM during initialization.
4497 *
4498 * @returns VBox status code.
4499 * @param pVM The cross context VM structure.
4500 */
4501VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4502{
4503 AssertPtr(pVM);
4504 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4505
4506 LogFlowFunc(("pVM=%p\n", pVM));
4507
4508 /*
4509 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4510 * without causing a #GP.
4511 */
4512 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4513 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4514 { /* likely */ }
4515 else
4516 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4517
4518 /*
4519 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4520 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4521 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4522 */
4523 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4524 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4525 || !pVM->hm.s.vmx.pRealModeTSS))
4526 {
4527 LogRelFunc(("Invalid real-on-v86 state.\n"));
4528 return VERR_INTERNAL_ERROR;
4529 }
4530
4531 /* Initialize these always, see hmR3InitFinalizeR0().*/
4532 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4533 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4534
4535 /* Setup the tagged-TLB flush handlers. */
4536 int rc = hmR0VmxSetupTaggedTlb(pVM);
4537 if (RT_FAILURE(rc))
4538 {
4539 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4540 return rc;
4541 }
4542
4543 /* Determine LBR capabilities. */
4544 if (pVM->hm.s.vmx.fLbr)
4545 {
4546 rc = hmR0VmxSetupLbrMsrRange(pVM);
4547 if (RT_FAILURE(rc))
4548 {
4549 LogRelFunc(("Failed to setup LBR MSR range. rc=%Rrc\n", rc));
4550 return rc;
4551 }
4552 }
4553
4554#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4555 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4556 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4557 {
4558 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4559 if (RT_SUCCESS(rc))
4560 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4561 else
4562 {
4563 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4564 return rc;
4565 }
4566 }
4567#endif
4568
4569 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4570 {
4571 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4572 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4573
4574 pVCpu->hmr0.s.vmx.pfnStartVm = hmR0VmxStartVmSelector;
4575
4576 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4577 if (RT_SUCCESS(rc))
4578 {
4579#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4580 if (pVM->cpum.ro.GuestFeatures.fVmx)
4581 {
4582 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hmr0.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4583 if (RT_SUCCESS(rc))
4584 { /* likely */ }
4585 else
4586 {
4587 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4588 return rc;
4589 }
4590 }
4591#endif
4592 }
4593 else
4594 {
4595 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4596 return rc;
4597 }
4598 }
4599
4600 return VINF_SUCCESS;
4601}
4602
4603
4604/**
4605 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4606 * the VMCS.
4607 * @returns CR4 for passing along to hmR0VmxExportHostSegmentRegs.
4608 */
4609static uint64_t hmR0VmxExportHostControlRegs(void)
4610{
4611 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4612 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4613 uint64_t uHostCr4 = ASMGetCR4();
4614 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, uHostCr4); AssertRC(rc);
4615 return uHostCr4;
4616}
4617
4618
4619/**
4620 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4621 * the host-state area in the VMCS.
4622 *
4623 * @returns VBox status code.
4624 * @param pVCpu The cross context virtual CPU structure.
4625 * @param uHostCr4 The host CR4 value.
4626 */
4627static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu, uint64_t uHostCr4)
4628{
4629 /*
4630 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4631 * will be messed up. We should -not- save the messed up state without restoring
4632 * the original host-state, see @bugref{7240}.
4633 *
4634 * This apparently can happen (most likely the FPU changes), deal with it rather than
4635 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4636 */
4637 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
4638 {
4639 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags,
4640 pVCpu->idCpu));
4641 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
4642 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
4643 }
4644
4645 /*
4646 * Get all the host info.
4647 * ASSUME it is safe to use rdfsbase and friends if the CR4.FSGSBASE bit is set
4648 * without also checking the cpuid bit.
4649 */
4650 uint32_t fRestoreHostFlags;
4651#if RT_INLINE_ASM_EXTERNAL
4652 if (uHostCr4 & X86_CR4_FSGSBASE)
4653 {
4654 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, true /*fHaveFsGsBase*/);
4655 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4656 }
4657 else
4658 {
4659 hmR0VmxExportHostSegmentRegsAsmHlp(&pVCpu->hmr0.s.vmx.RestoreHost, false /*fHaveFsGsBase*/);
4660 fRestoreHostFlags = 0;
4661 }
4662 RTSEL uSelES = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES;
4663 RTSEL uSelDS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS;
4664 RTSEL uSelFS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS;
4665 RTSEL uSelGS = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS;
4666#else
4667 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR = ASMGetTR();
4668 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS = ASMGetSS();
4669 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS = ASMGetCS();
4670 ASMGetGDTR((PRTGDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr);
4671 ASMGetIDTR((PRTIDTR)&pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr);
4672 if (uHostCr4 & X86_CR4_FSGSBASE)
4673 {
4674 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMGetFSBase();
4675 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMGetGSBase();
4676 fRestoreHostFlags = VMX_RESTORE_HOST_CAN_USE_WRFSBASE_AND_WRGSBASE;
4677 }
4678 else
4679 {
4680 pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase = ASMRdMsr(MSR_K8_FS_BASE);
4681 pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase = ASMRdMsr(MSR_K8_GS_BASE);
4682 fRestoreHostFlags = 0;
4683 }
4684 RTSEL uSelES, uSelDS, uSelFS, uSelGS;
4685 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelDS = uSelDS = ASMGetDS();
4686 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelES = uSelES = ASMGetES();
4687 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelFS = uSelFS = ASMGetFS();
4688 pVCpu->hmr0.s.vmx.RestoreHost.uHostSelGS = uSelGS = ASMGetGS();
4689#endif
4690
4691 /*
4692 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4693 * gain VM-entry and restore them before we get preempted.
4694 *
4695 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4696 */
4697 RTSEL const uSelAll = uSelFS | uSelGS | uSelES | uSelDS;
4698 if (uSelAll & (X86_SEL_RPL | X86_SEL_LDT))
4699 {
4700 if (!(uSelAll & X86_SEL_LDT))
4701 {
4702#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4703 do { \
4704 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4705 if ((a_uVmcsVar) & X86_SEL_RPL) \
4706 { \
4707 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4708 (a_uVmcsVar) = 0; \
4709 } \
4710 } while (0)
4711 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4712 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4713 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4714 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4715#undef VMXLOCAL_ADJUST_HOST_SEG
4716 }
4717 else
4718 {
4719#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_uVmcsVar) \
4720 do { \
4721 (a_uVmcsVar) = pVCpu->hmr0.s.vmx.RestoreHost.uHostSel##a_Seg; \
4722 if ((a_uVmcsVar) & (X86_SEL_RPL | X86_SEL_LDT)) \
4723 { \
4724 if (!((a_uVmcsVar) & X86_SEL_LDT)) \
4725 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4726 else \
4727 { \
4728 uint32_t const fAttr = ASMGetSegAttr(a_uVmcsVar); \
4729 if ((fAttr & X86_DESC_P) && fAttr != UINT32_MAX) \
4730 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4731 } \
4732 (a_uVmcsVar) = 0; \
4733 } \
4734 } while (0)
4735 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4736 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4737 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4738 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4739#undef VMXLOCAL_ADJUST_HOST_SEG
4740 }
4741 }
4742
4743 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4744 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR);
4745 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS & X86_SEL_LDT)); Assert(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS);
4746 Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_RPL)); Assert(!(pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS & X86_SEL_LDT));
4747 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4748 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4749 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4750 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4751
4752 /*
4753 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4754 * them to the maximum limit (0xffff) on every VM-exit.
4755 */
4756 if (pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb != 0xffff)
4757 fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4758
4759 /*
4760 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4761 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4762 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4763 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4764 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4765 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4766 * at 0xffff on hosts where we are sure it won't cause trouble.
4767 */
4768#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4769 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb < 0x0fff)
4770#else
4771 if (pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.cb != 0xffff)
4772#endif
4773 fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4774
4775 /*
4776 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4777 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4778 * RPL should be too in most cases.
4779 */
4780 RTSEL const uSelTR = pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR;
4781 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb,
4782 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb),
4783 VERR_VMX_INVALID_HOST_STATE);
4784
4785 PCX86DESCHC pDesc = (PCX86DESCHC)(pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr + (uSelTR & X86_SEL_MASK));
4786 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4787
4788 /*
4789 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4790 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4791 * restoration if the host has something else. Task switching is not supported in 64-bit
4792 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4793 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4794 *
4795 * [1] See Intel spec. 3.5 "System Descriptor Types".
4796 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4797 */
4798 Assert(pDesc->System.u4Type == 11);
4799 if ( pDesc->System.u16LimitLow != 0x67
4800 || pDesc->System.u4LimitHigh)
4801 {
4802 fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4803
4804 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4805 PVM pVM = pVCpu->CTX_SUFF(pVM);
4806 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4807 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4808 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4809 {
4810 /* The GDT is read-only but the writable GDT is available. */
4811 fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4812 pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.cb = pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.cb;
4813 int rc = SUPR0GetCurrentGdtRw(&pVCpu->hmr0.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4814 AssertRCReturn(rc, rc);
4815 }
4816 }
4817
4818 pVCpu->hmr0.s.vmx.fRestoreHostFlags = fRestoreHostFlags;
4819
4820 /*
4821 * Do all the VMCS updates in one block to assist nested virtualization.
4822 */
4823 int rc;
4824 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelCS); AssertRC(rc);
4825 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelSS); AssertRC(rc);
4826 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4827 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4828 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4829 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4830 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, pVCpu->hmr0.s.vmx.RestoreHost.uHostSelTR); AssertRC(rc);
4831 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostGdtr.uAddr); AssertRC(rc);
4832 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, pVCpu->hmr0.s.vmx.RestoreHost.HostIdtr.uAddr); AssertRC(rc);
4833 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase); AssertRC(rc);
4834 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostFSBase); AssertRC(rc);
4835 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, pVCpu->hmr0.s.vmx.RestoreHost.uHostGSBase); AssertRC(rc);
4836
4837 return VINF_SUCCESS;
4838}
4839
4840
4841/**
4842 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4843 * host-state area of the VMCS.
4844 *
4845 * These MSRs will be automatically restored on the host after every successful
4846 * VM-exit.
4847 *
4848 * @param pVCpu The cross context virtual CPU structure.
4849 *
4850 * @remarks No-long-jump zone!!!
4851 */
4852static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4853{
4854 AssertPtr(pVCpu);
4855
4856 /*
4857 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4858 * rather than swapping them on every VM-entry.
4859 */
4860 hmR0VmxLazySaveHostMsrs(pVCpu);
4861
4862 /*
4863 * Host Sysenter MSRs.
4864 */
4865 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4866 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4867 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4868
4869 /*
4870 * Host EFER MSR.
4871 *
4872 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4873 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4874 */
4875 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4876 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4877 {
4878 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4879 AssertRC(rc);
4880 }
4881
4882 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4883 * hmR0VmxExportGuestEntryExitCtls(). */
4884}
4885
4886
4887/**
4888 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4889 *
4890 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4891 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4892 *
4893 * @returns true if we need to load guest EFER, false otherwise.
4894 * @param pVCpu The cross context virtual CPU structure.
4895 * @param pVmxTransient The VMX-transient structure.
4896 *
4897 * @remarks Requires EFER, CR4.
4898 * @remarks No-long-jump zone!!!
4899 */
4900static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4901{
4902#ifdef HMVMX_ALWAYS_SWAP_EFER
4903 RT_NOREF2(pVCpu, pVmxTransient);
4904 return true;
4905#else
4906 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4907 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4908 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4909 uint64_t const u64GuestEfer = pCtx->msrEFER;
4910
4911# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4912 /*
4913 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4914 * the nested-guest.
4915 */
4916 if ( pVmxTransient->fIsNestedGuest
4917 && ( CPUMIsGuestVmxEntryCtlsSet(pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4918 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4919 || CPUMIsGuestVmxExitCtlsSet(pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4920 return true;
4921# else
4922 RT_NOREF(pVmxTransient);
4923#endif
4924
4925 /*
4926 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4927 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4928 */
4929 if ( CPUMIsGuestInLongModeEx(pCtx)
4930 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4931 return true;
4932
4933 /*
4934 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4935 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4936 *
4937 * See Intel spec. 4.5 "IA-32e Paging".
4938 * See Intel spec. 4.1.1 "Three Paging Modes".
4939 *
4940 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4941 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4942 */
4943 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4944 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4945 if ( (pCtx->cr4 & X86_CR4_PAE)
4946 && (pCtx->cr0 & X86_CR0_PG))
4947 {
4948 /*
4949 * If nested paging is not used, verify that the guest paging mode matches the
4950 * shadow paging mode which is/will be placed in the VMCS (which is what will
4951 * actually be used while executing the guest and not the CR4 shadow value).
4952 */
4953 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4954 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4955 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4956 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4957 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4958 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4959 {
4960 /* Verify that the host is NX capable. */
4961 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4962 return true;
4963 }
4964 }
4965
4966 return false;
4967#endif
4968}
4969
4970
4971/**
4972 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4973 * VMCS.
4974 *
4975 * This is typically required when the guest changes paging mode.
4976 *
4977 * @returns VBox status code.
4978 * @param pVCpu The cross context virtual CPU structure.
4979 * @param pVmxTransient The VMX-transient structure.
4980 *
4981 * @remarks Requires EFER.
4982 * @remarks No-long-jump zone!!!
4983 */
4984static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4985{
4986 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4987 {
4988 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4989 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4990
4991 /*
4992 * VM-entry controls.
4993 */
4994 {
4995 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4996 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4997
4998 /*
4999 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5000 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5001 *
5002 * For nested-guests, this is a mandatory VM-entry control. It's also
5003 * required because we do not want to leak host bits to the nested-guest.
5004 */
5005 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5006
5007 /*
5008 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5009 *
5010 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5011 * required to get the nested-guest working with hardware-assisted VMX execution.
5012 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
5013 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
5014 * here rather than while merging the guest VMCS controls.
5015 */
5016 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5017 {
5018 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
5019 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5020 }
5021 else
5022 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5023
5024 /*
5025 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5026 *
5027 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5028 * regardless of whether the nested-guest VMCS specifies it because we are free to
5029 * load whatever MSRs we require and we do not need to modify the guest visible copy
5030 * of the VM-entry MSR load area.
5031 */
5032 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5033 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5034 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5035 else
5036 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5037
5038 /*
5039 * The following should -not- be set (since we're not in SMM mode):
5040 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5041 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5042 */
5043
5044 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5045 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5046
5047 if ((fVal & fZap) == fVal)
5048 { /* likely */ }
5049 else
5050 {
5051 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5052 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
5053 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5054 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5055 }
5056
5057 /* Commit it to the VMCS. */
5058 if (pVmcsInfo->u32EntryCtls != fVal)
5059 {
5060 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5061 AssertRC(rc);
5062 pVmcsInfo->u32EntryCtls = fVal;
5063 }
5064 }
5065
5066 /*
5067 * VM-exit controls.
5068 */
5069 {
5070 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5071 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5072
5073 /*
5074 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5075 * supported the 1-setting of this bit.
5076 *
5077 * For nested-guests, we set the "save debug controls" as the converse
5078 * "load debug controls" is mandatory for nested-guests anyway.
5079 */
5080 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5081
5082 /*
5083 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5084 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5085 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5086 * hmR0VmxExportHostMsrs().
5087 *
5088 * For nested-guests, we always set this bit as we do not support 32-bit
5089 * hosts.
5090 */
5091 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5092
5093 /*
5094 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5095 *
5096 * For nested-guests, we should use the "save IA32_EFER" control if we also
5097 * used the "load IA32_EFER" control while exporting VM-entry controls.
5098 */
5099 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5100 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
5101 {
5102 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5103 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5104 }
5105
5106 /*
5107 * Enable saving of the VMX-preemption timer value on VM-exit.
5108 * For nested-guests, currently not exposed/used.
5109 */
5110 if ( pVM->hm.s.vmx.fUsePreemptTimer
5111 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5112 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5113
5114 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5115 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5116
5117 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5118 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5119 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5120
5121 if ((fVal & fZap) == fVal)
5122 { /* likely */ }
5123 else
5124 {
5125 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5126 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5127 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5128 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5129 }
5130
5131 /* Commit it to the VMCS. */
5132 if (pVmcsInfo->u32ExitCtls != fVal)
5133 {
5134 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5135 AssertRC(rc);
5136 pVmcsInfo->u32ExitCtls = fVal;
5137 }
5138 }
5139
5140 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5141 }
5142 return VINF_SUCCESS;
5143}
5144
5145
5146/**
5147 * Sets the TPR threshold in the VMCS.
5148 *
5149 * @param pVmcsInfo The VMCS info. object.
5150 * @param u32TprThreshold The TPR threshold (task-priority class only).
5151 */
5152DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5153{
5154 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5155 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5156 RT_NOREF(pVmcsInfo);
5157 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5158 AssertRC(rc);
5159}
5160
5161
5162/**
5163 * Exports the guest APIC TPR state into the VMCS.
5164 *
5165 * @param pVCpu The cross context virtual CPU structure.
5166 * @param pVmxTransient The VMX-transient structure.
5167 *
5168 * @remarks No-long-jump zone!!!
5169 */
5170static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5171{
5172 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5173 {
5174 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5175
5176 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5177 if (!pVmxTransient->fIsNestedGuest)
5178 {
5179 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5180 && APICIsEnabled(pVCpu))
5181 {
5182 /*
5183 * Setup TPR shadowing.
5184 */
5185 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5186 {
5187 bool fPendingIntr = false;
5188 uint8_t u8Tpr = 0;
5189 uint8_t u8PendingIntr = 0;
5190 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5191 AssertRC(rc);
5192
5193 /*
5194 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5195 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5196 * priority of the pending interrupt so we can deliver the interrupt. If there
5197 * are no interrupts pending, set threshold to 0 to not cause any
5198 * TPR-below-threshold VM-exits.
5199 */
5200 uint32_t u32TprThreshold = 0;
5201 if (fPendingIntr)
5202 {
5203 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5204 (which is the Task-Priority Class). */
5205 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5206 const uint8_t u8TprPriority = u8Tpr >> 4;
5207 if (u8PendingPriority <= u8TprPriority)
5208 u32TprThreshold = u8PendingPriority;
5209 }
5210
5211 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
5212 }
5213 }
5214 }
5215 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5216 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5217 }
5218}
5219
5220
5221/**
5222 * Gets the guest interruptibility-state and updates related force-flags.
5223 *
5224 * @returns Guest's interruptibility-state.
5225 * @param pVCpu The cross context virtual CPU structure.
5226 *
5227 * @remarks No-long-jump zone!!!
5228 */
5229static uint32_t hmR0VmxGetGuestIntrStateAndUpdateFFs(PVMCPUCC pVCpu)
5230{
5231 /*
5232 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5233 */
5234 uint32_t fIntrState = 0;
5235 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5236 {
5237 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5238 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5239
5240 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5241 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5242 {
5243 if (pCtx->eflags.Bits.u1IF)
5244 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5245 else
5246 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5247 }
5248 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5249 {
5250 /*
5251 * We can clear the inhibit force flag as even if we go back to the recompiler
5252 * without executing guest code in VT-x, the flag's condition to be cleared is
5253 * met and thus the cleared state is correct.
5254 */
5255 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5256 }
5257 }
5258
5259 /*
5260 * Check if we should inhibit NMI delivery.
5261 */
5262 if (CPUMIsGuestNmiBlocking(pVCpu))
5263 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5264
5265 /*
5266 * Validate.
5267 */
5268#ifdef VBOX_STRICT
5269 /* We don't support block-by-SMI yet.*/
5270 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
5271
5272 /* Block-by-STI must not be set when interrupts are disabled. */
5273 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
5274 {
5275 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5276 Assert(pVCpu->cpum.GstCtx.eflags.u & X86_EFL_IF);
5277 }
5278#endif
5279
5280 return fIntrState;
5281}
5282
5283
5284/**
5285 * Exports the exception intercepts required for guest execution in the VMCS.
5286 *
5287 * @param pVCpu The cross context virtual CPU structure.
5288 * @param pVmxTransient The VMX-transient structure.
5289 *
5290 * @remarks No-long-jump zone!!!
5291 */
5292static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5293{
5294 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5295 {
5296 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5297 if ( !pVmxTransient->fIsNestedGuest
5298 && pVCpu->hm.s.fGIMTrapXcptUD)
5299 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5300 else
5301 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5302
5303 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5304 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5305 }
5306}
5307
5308
5309/**
5310 * Exports the guest's RIP into the guest-state area in the VMCS.
5311 *
5312 * @param pVCpu The cross context virtual CPU structure.
5313 *
5314 * @remarks No-long-jump zone!!!
5315 */
5316static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5317{
5318 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5319 {
5320 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5321
5322 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5323 AssertRC(rc);
5324
5325 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5326 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5327 }
5328}
5329
5330
5331/**
5332 * Exports the guest's RSP into the guest-state area in the VMCS.
5333 *
5334 * @param pVCpu The cross context virtual CPU structure.
5335 *
5336 * @remarks No-long-jump zone!!!
5337 */
5338static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5339{
5340 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5341 {
5342 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5343
5344 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5345 AssertRC(rc);
5346
5347 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5348 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5349 }
5350}
5351
5352
5353/**
5354 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5355 *
5356 * @param pVCpu The cross context virtual CPU structure.
5357 * @param pVmxTransient The VMX-transient structure.
5358 *
5359 * @remarks No-long-jump zone!!!
5360 */
5361static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5362{
5363 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5364 {
5365 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5366
5367 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5368 Let us assert it as such and use 32-bit VMWRITE. */
5369 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5370 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5371 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5372 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5373
5374 /*
5375 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5376 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5377 * can run the real-mode guest code under Virtual 8086 mode.
5378 */
5379 PVMXVMCSINFOSHARED pVmcsInfo = pVmxTransient->pVmcsInfo->pShared;
5380 if (pVmcsInfo->RealMode.fRealOnV86Active)
5381 {
5382 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5383 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5384 Assert(!pVmxTransient->fIsNestedGuest);
5385 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5386 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5387 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5388 }
5389
5390 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5391 AssertRC(rc);
5392
5393 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5394 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5395 }
5396}
5397
5398
5399#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5400/**
5401 * Copies the nested-guest VMCS to the shadow VMCS.
5402 *
5403 * @returns VBox status code.
5404 * @param pVCpu The cross context virtual CPU structure.
5405 * @param pVmcsInfo The VMCS info. object.
5406 *
5407 * @remarks No-long-jump zone!!!
5408 */
5409static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5410{
5411 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5412 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5413
5414 /*
5415 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5416 * current VMCS, as we may try saving guest lazy MSRs.
5417 *
5418 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5419 * calling the import VMCS code which is currently performing the guest MSR reads
5420 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5421 * and the rest of the VMX leave session machinery.
5422 */
5423 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5424
5425 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5426 if (RT_SUCCESS(rc))
5427 {
5428 /*
5429 * Copy all guest read/write VMCS fields.
5430 *
5431 * We don't check for VMWRITE failures here for performance reasons and
5432 * because they are not expected to fail, barring irrecoverable conditions
5433 * like hardware errors.
5434 */
5435 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5436 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5437 {
5438 uint64_t u64Val;
5439 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5440 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5441 VMXWriteVmcs64(uVmcsField, u64Val);
5442 }
5443
5444 /*
5445 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5446 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5447 */
5448 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5449 {
5450 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5451 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5452 {
5453 uint64_t u64Val;
5454 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5455 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5456 VMXWriteVmcs64(uVmcsField, u64Val);
5457 }
5458 }
5459
5460 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5461 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5462 }
5463
5464 ASMSetFlags(fEFlags);
5465 return rc;
5466}
5467
5468
5469/**
5470 * Copies the shadow VMCS to the nested-guest VMCS.
5471 *
5472 * @returns VBox status code.
5473 * @param pVCpu The cross context virtual CPU structure.
5474 * @param pVmcsInfo The VMCS info. object.
5475 *
5476 * @remarks Called with interrupts disabled.
5477 */
5478static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5479{
5480 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5481 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5482 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5483
5484 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5485 if (RT_SUCCESS(rc))
5486 {
5487 /*
5488 * Copy guest read/write fields from the shadow VMCS.
5489 * Guest read-only fields cannot be modified, so no need to copy them.
5490 *
5491 * We don't check for VMREAD failures here for performance reasons and
5492 * because they are not expected to fail, barring irrecoverable conditions
5493 * like hardware errors.
5494 */
5495 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5496 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5497 {
5498 uint64_t u64Val;
5499 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5500 VMXReadVmcs64(uVmcsField, &u64Val);
5501 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5502 }
5503
5504 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5505 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5506 }
5507 return rc;
5508}
5509
5510
5511/**
5512 * Enables VMCS shadowing for the given VMCS info. object.
5513 *
5514 * @param pVmcsInfo The VMCS info. object.
5515 *
5516 * @remarks No-long-jump zone!!!
5517 */
5518static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5519{
5520 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5521 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5522 {
5523 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5524 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5525 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5526 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5527 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5528 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5529 Log4Func(("Enabled\n"));
5530 }
5531}
5532
5533
5534/**
5535 * Disables VMCS shadowing for the given VMCS info. object.
5536 *
5537 * @param pVmcsInfo The VMCS info. object.
5538 *
5539 * @remarks No-long-jump zone!!!
5540 */
5541static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5542{
5543 /*
5544 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5545 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5546 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5547 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5548 *
5549 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5550 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5551 */
5552 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5553 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5554 {
5555 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5556 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5557 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5558 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5559 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5560 Log4Func(("Disabled\n"));
5561 }
5562}
5563#endif
5564
5565
5566/**
5567 * Exports the guest hardware-virtualization state.
5568 *
5569 * @returns VBox status code.
5570 * @param pVCpu The cross context virtual CPU structure.
5571 * @param pVmxTransient The VMX-transient structure.
5572 *
5573 * @remarks No-long-jump zone!!!
5574 */
5575static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5576{
5577 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5578 {
5579#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5580 /*
5581 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5582 * VMCS shadowing.
5583 */
5584 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5585 {
5586 /*
5587 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5588 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5589 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5590 *
5591 * We check for VMX root mode here in case the guest executes VMXOFF without
5592 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5593 * not clear the current VMCS pointer.
5594 */
5595 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5596 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5597 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5598 && CPUMIsGuestVmxCurrentVmcsValid(&pVCpu->cpum.GstCtx))
5599 {
5600 /* Paranoia. */
5601 Assert(!pVmxTransient->fIsNestedGuest);
5602
5603 /*
5604 * For performance reasons, also check if the nested hypervisor's current VMCS
5605 * was newly loaded or modified before copying it to the shadow VMCS.
5606 */
5607 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5608 {
5609 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5610 AssertRCReturn(rc, rc);
5611 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5612 }
5613 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5614 }
5615 else
5616 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5617 }
5618#else
5619 NOREF(pVmxTransient);
5620#endif
5621 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5622 }
5623 return VINF_SUCCESS;
5624}
5625
5626
5627/**
5628 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5629 *
5630 * The guest FPU state is always pre-loaded hence we don't need to bother about
5631 * sharing FPU related CR0 bits between the guest and host.
5632 *
5633 * @returns VBox status code.
5634 * @param pVCpu The cross context virtual CPU structure.
5635 * @param pVmxTransient The VMX-transient structure.
5636 *
5637 * @remarks No-long-jump zone!!!
5638 */
5639static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5640{
5641 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5642 {
5643 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5644 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5645
5646 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5647 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5648 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5649 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5650 else
5651 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5652
5653 if (!pVmxTransient->fIsNestedGuest)
5654 {
5655 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5656 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5657 uint64_t const u64ShadowCr0 = u64GuestCr0;
5658 Assert(!RT_HI_U32(u64GuestCr0));
5659
5660 /*
5661 * Setup VT-x's view of the guest CR0.
5662 */
5663 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5664 if (pVM->hm.s.fNestedPaging)
5665 {
5666 if (CPUMIsGuestPagingEnabled(pVCpu))
5667 {
5668 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5669 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5670 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5671 }
5672 else
5673 {
5674 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5675 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5676 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5677 }
5678
5679 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5680 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5681 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5682 }
5683 else
5684 {
5685 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5686 u64GuestCr0 |= X86_CR0_WP;
5687 }
5688
5689 /*
5690 * Guest FPU bits.
5691 *
5692 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5693 * using CR0.TS.
5694 *
5695 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5696 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5697 */
5698 u64GuestCr0 |= X86_CR0_NE;
5699
5700 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5701 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5702
5703 /*
5704 * Update exception intercepts.
5705 */
5706 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5707 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5708 {
5709 Assert(PDMVmmDevHeapIsEnabled(pVM));
5710 Assert(pVM->hm.s.vmx.pRealModeTSS);
5711 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5712 }
5713 else
5714 {
5715 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5716 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5717 if (fInterceptMF)
5718 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5719 }
5720
5721 /* Additional intercepts for debugging, define these yourself explicitly. */
5722#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5723 uXcptBitmap |= 0
5724 | RT_BIT(X86_XCPT_BP)
5725 | RT_BIT(X86_XCPT_DE)
5726 | RT_BIT(X86_XCPT_NM)
5727 | RT_BIT(X86_XCPT_TS)
5728 | RT_BIT(X86_XCPT_UD)
5729 | RT_BIT(X86_XCPT_NP)
5730 | RT_BIT(X86_XCPT_SS)
5731 | RT_BIT(X86_XCPT_GP)
5732 | RT_BIT(X86_XCPT_PF)
5733 | RT_BIT(X86_XCPT_MF)
5734 ;
5735#elif defined(HMVMX_ALWAYS_TRAP_PF)
5736 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5737#endif
5738 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5739 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5740 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5741
5742 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5743 u64GuestCr0 |= fSetCr0;
5744 u64GuestCr0 &= fZapCr0;
5745 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5746
5747 /* Commit the CR0 and related fields to the guest VMCS. */
5748 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5749 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5750 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5751 {
5752 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5753 AssertRC(rc);
5754 }
5755 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5756 {
5757 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5758 AssertRC(rc);
5759 }
5760
5761 /* Update our caches. */
5762 pVmcsInfo->u32ProcCtls = uProcCtls;
5763 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5764
5765 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5766 }
5767 else
5768 {
5769 /*
5770 * With nested-guests, we may have extended the guest/host mask here since we
5771 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5772 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5773 * originally supplied. We must copy those bits from the nested-guest CR0 into
5774 * the nested-guest CR0 read-shadow.
5775 */
5776 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5777 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5778 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(&pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5779 Assert(!RT_HI_U32(u64GuestCr0));
5780 Assert(u64GuestCr0 & X86_CR0_NE);
5781
5782 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5783 u64GuestCr0 |= fSetCr0;
5784 u64GuestCr0 &= fZapCr0;
5785 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5786
5787 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5788 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5789 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5790
5791 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5792 }
5793
5794 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5795 }
5796
5797 return VINF_SUCCESS;
5798}
5799
5800
5801/**
5802 * Exports the guest control registers (CR3, CR4) into the guest-state area
5803 * in the VMCS.
5804 *
5805 * @returns VBox strict status code.
5806 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5807 * without unrestricted guest access and the VMMDev is not presently
5808 * mapped (e.g. EFI32).
5809 *
5810 * @param pVCpu The cross context virtual CPU structure.
5811 * @param pVmxTransient The VMX-transient structure.
5812 *
5813 * @remarks No-long-jump zone!!!
5814 */
5815static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5816{
5817 int rc = VINF_SUCCESS;
5818 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5819
5820 /*
5821 * Guest CR2.
5822 * It's always loaded in the assembler code. Nothing to do here.
5823 */
5824
5825 /*
5826 * Guest CR3.
5827 */
5828 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5829 {
5830 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5831
5832 if (pVM->hm.s.fNestedPaging)
5833 {
5834 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5835 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5836
5837 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5838 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5839 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5840 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5841
5842 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5843 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5844 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5845
5846 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5847 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5848 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5849 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5850 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5851 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5852 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5853
5854 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5855 AssertRC(rc);
5856
5857 uint64_t u64GuestCr3;
5858 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5859 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5860 || CPUMIsGuestPagingEnabledEx(pCtx))
5861 {
5862 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5863 if (CPUMIsGuestInPAEModeEx(pCtx))
5864 {
5865 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5866 AssertRC(rc);
5867 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5868 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5869 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5870 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5871 }
5872
5873 /*
5874 * The guest's view of its CR3 is unblemished with nested paging when the
5875 * guest is using paging or we have unrestricted guest execution to handle
5876 * the guest when it's not using paging.
5877 */
5878 u64GuestCr3 = pCtx->cr3;
5879 }
5880 else
5881 {
5882 /*
5883 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5884 * thinks it accesses physical memory directly, we use our identity-mapped
5885 * page table to map guest-linear to guest-physical addresses. EPT takes care
5886 * of translating it to host-physical addresses.
5887 */
5888 RTGCPHYS GCPhys;
5889 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5890
5891 /* We obtain it here every time as the guest could have relocated this PCI region. */
5892 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5893 if (RT_SUCCESS(rc))
5894 { /* likely */ }
5895 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5896 {
5897 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5898 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5899 }
5900 else
5901 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5902
5903 u64GuestCr3 = GCPhys;
5904 }
5905
5906 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5907 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5908 AssertRC(rc);
5909 }
5910 else
5911 {
5912 Assert(!pVmxTransient->fIsNestedGuest);
5913 /* Non-nested paging case, just use the hypervisor's CR3. */
5914 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5915
5916 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5917 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5918 AssertRC(rc);
5919 }
5920
5921 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5922 }
5923
5924 /*
5925 * Guest CR4.
5926 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5927 */
5928 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5929 {
5930 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5931 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5932
5933 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5934 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5935
5936 /*
5937 * With nested-guests, we may have extended the guest/host mask here (since we
5938 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5939 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5940 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5941 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5942 */
5943 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5944 uint64_t u64GuestCr4 = pCtx->cr4;
5945 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5946 ? pCtx->cr4
5947 : CPUMGetGuestVmxMaskedCr4(pCtx, pVmcsInfo->u64Cr4Mask);
5948 Assert(!RT_HI_U32(u64GuestCr4));
5949
5950 /*
5951 * Setup VT-x's view of the guest CR4.
5952 *
5953 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5954 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5955 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5956 *
5957 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5958 */
5959 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
5960 {
5961 Assert(pVM->hm.s.vmx.pRealModeTSS);
5962 Assert(PDMVmmDevHeapIsEnabled(pVM));
5963 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5964 }
5965
5966 if (pVM->hm.s.fNestedPaging)
5967 {
5968 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5969 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5970 {
5971 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5972 u64GuestCr4 |= X86_CR4_PSE;
5973 /* Our identity mapping is a 32-bit page directory. */
5974 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5975 }
5976 /* else use guest CR4.*/
5977 }
5978 else
5979 {
5980 Assert(!pVmxTransient->fIsNestedGuest);
5981
5982 /*
5983 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5984 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5985 */
5986 switch (pVCpu->hm.s.enmShadowMode)
5987 {
5988 case PGMMODE_REAL: /* Real-mode. */
5989 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5990 case PGMMODE_32_BIT: /* 32-bit paging. */
5991 {
5992 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5993 break;
5994 }
5995
5996 case PGMMODE_PAE: /* PAE paging. */
5997 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5998 {
5999 u64GuestCr4 |= X86_CR4_PAE;
6000 break;
6001 }
6002
6003 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6004 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6005 {
6006#ifdef VBOX_WITH_64_BITS_GUESTS
6007 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
6008 Assert(u64GuestCr4 & X86_CR4_PAE);
6009 break;
6010#endif
6011 }
6012 default:
6013 AssertFailed();
6014 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6015 }
6016 }
6017
6018 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
6019 u64GuestCr4 |= fSetCr4;
6020 u64GuestCr4 &= fZapCr4;
6021
6022 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6023 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
6024 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
6025
6026 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6027 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6028 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
6029 {
6030 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
6031 hmR0VmxUpdateStartVmFunction(pVCpu);
6032 }
6033
6034 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6035
6036 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6037 }
6038 return rc;
6039}
6040
6041
6042/**
6043 * Exports the guest debug registers into the guest-state area in the VMCS.
6044 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6045 *
6046 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6047 *
6048 * @returns VBox status code.
6049 * @param pVCpu The cross context virtual CPU structure.
6050 * @param pVmxTransient The VMX-transient structure.
6051 *
6052 * @remarks No-long-jump zone!!!
6053 */
6054static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6055{
6056 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6057
6058 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6059 * stepping. */
6060 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6061 if (pVmxTransient->fIsNestedGuest)
6062 {
6063 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6064 AssertRC(rc);
6065
6066 /* Always intercept Mov DRx accesses for the nested-guest for now. */
6067 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6068 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
6069 AssertRC(rc);
6070 return VINF_SUCCESS;
6071 }
6072
6073#ifdef VBOX_STRICT
6074 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6075 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6076 {
6077 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6078 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6079 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6080 }
6081#endif
6082
6083 bool fSteppingDB = false;
6084 bool fInterceptMovDRx = false;
6085 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6086 if (pVCpu->hm.s.fSingleInstruction)
6087 {
6088 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6089 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6090 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6091 {
6092 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6093 Assert(fSteppingDB == false);
6094 }
6095 else
6096 {
6097 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6098 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6099 pVCpu->hmr0.s.fClearTrapFlag = true;
6100 fSteppingDB = true;
6101 }
6102 }
6103
6104 uint64_t u64GuestDr7;
6105 if ( fSteppingDB
6106 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6107 {
6108 /*
6109 * Use the combined guest and host DRx values found in the hypervisor register set
6110 * because the hypervisor debugger has breakpoints active or someone is single stepping
6111 * on the host side without a monitor trap flag.
6112 *
6113 * Note! DBGF expects a clean DR6 state before executing guest code.
6114 */
6115 if (!CPUMIsHyperDebugStateActive(pVCpu))
6116 {
6117 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6118 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6119 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6120 }
6121
6122 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6123 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
6124 pVCpu->hmr0.s.fUsingHyperDR7 = true;
6125 fInterceptMovDRx = true;
6126 }
6127 else
6128 {
6129 /*
6130 * If the guest has enabled debug registers, we need to load them prior to
6131 * executing guest code so they'll trigger at the right time.
6132 */
6133 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DR7);
6134 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6135 {
6136 if (!CPUMIsGuestDebugStateActive(pVCpu))
6137 {
6138 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6139 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6140 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6141 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6142 }
6143 Assert(!fInterceptMovDRx);
6144 }
6145 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6146 {
6147 /*
6148 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6149 * must intercept #DB in order to maintain a correct DR6 guest value, and
6150 * because we need to intercept it to prevent nested #DBs from hanging the
6151 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6152 */
6153 fInterceptMovDRx = true;
6154 }
6155
6156 /* Update DR7 with the actual guest value. */
6157 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6158 pVCpu->hmr0.s.fUsingHyperDR7 = false;
6159 }
6160
6161 if (fInterceptMovDRx)
6162 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6163 else
6164 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6165
6166 /*
6167 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6168 * monitor-trap flag and update our cache.
6169 */
6170 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6171 {
6172 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6173 AssertRC(rc);
6174 pVmcsInfo->u32ProcCtls = uProcCtls;
6175 }
6176
6177 /*
6178 * Update guest DR7.
6179 */
6180 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
6181 AssertRC(rc);
6182
6183 /*
6184 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6185 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6186 *
6187 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6188 */
6189 if (fSteppingDB)
6190 {
6191 Assert(pVCpu->hm.s.fSingleInstruction);
6192 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6193
6194 uint32_t fIntrState = 0;
6195 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6196 AssertRC(rc);
6197
6198 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6199 {
6200 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6201 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6202 AssertRC(rc);
6203 }
6204 }
6205
6206 return VINF_SUCCESS;
6207}
6208
6209
6210#ifdef VBOX_STRICT
6211/**
6212 * Strict function to validate segment registers.
6213 *
6214 * @param pVCpu The cross context virtual CPU structure.
6215 * @param pVmcsInfo The VMCS info. object.
6216 *
6217 * @remarks Will import guest CR0 on strict builds during validation of
6218 * segments.
6219 */
6220static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
6221{
6222 /*
6223 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6224 *
6225 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6226 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6227 * unusable bit and doesn't change the guest-context value.
6228 */
6229 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6230 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6231 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6232 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6233 && ( !CPUMIsGuestInRealModeEx(pCtx)
6234 && !CPUMIsGuestInV86ModeEx(pCtx)))
6235 {
6236 /* Protected mode checks */
6237 /* CS */
6238 Assert(pCtx->cs.Attr.n.u1Present);
6239 Assert(!(pCtx->cs.Attr.u & 0xf00));
6240 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6241 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6242 || !(pCtx->cs.Attr.n.u1Granularity));
6243 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6244 || (pCtx->cs.Attr.n.u1Granularity));
6245 /* CS cannot be loaded with NULL in protected mode. */
6246 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6247 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6248 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6249 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6250 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6251 else
6252 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6253 /* SS */
6254 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6255 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6256 if ( !(pCtx->cr0 & X86_CR0_PE)
6257 || pCtx->cs.Attr.n.u4Type == 3)
6258 {
6259 Assert(!pCtx->ss.Attr.n.u2Dpl);
6260 }
6261 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6262 {
6263 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6264 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6265 Assert(pCtx->ss.Attr.n.u1Present);
6266 Assert(!(pCtx->ss.Attr.u & 0xf00));
6267 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6268 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6269 || !(pCtx->ss.Attr.n.u1Granularity));
6270 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6271 || (pCtx->ss.Attr.n.u1Granularity));
6272 }
6273 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6274 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6275 {
6276 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6277 Assert(pCtx->ds.Attr.n.u1Present);
6278 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6279 Assert(!(pCtx->ds.Attr.u & 0xf00));
6280 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6281 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6282 || !(pCtx->ds.Attr.n.u1Granularity));
6283 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6284 || (pCtx->ds.Attr.n.u1Granularity));
6285 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6286 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6287 }
6288 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6289 {
6290 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6291 Assert(pCtx->es.Attr.n.u1Present);
6292 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6293 Assert(!(pCtx->es.Attr.u & 0xf00));
6294 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6295 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6296 || !(pCtx->es.Attr.n.u1Granularity));
6297 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6298 || (pCtx->es.Attr.n.u1Granularity));
6299 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6300 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6301 }
6302 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6303 {
6304 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6305 Assert(pCtx->fs.Attr.n.u1Present);
6306 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6307 Assert(!(pCtx->fs.Attr.u & 0xf00));
6308 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6309 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6310 || !(pCtx->fs.Attr.n.u1Granularity));
6311 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6312 || (pCtx->fs.Attr.n.u1Granularity));
6313 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6314 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6315 }
6316 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6317 {
6318 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6319 Assert(pCtx->gs.Attr.n.u1Present);
6320 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6321 Assert(!(pCtx->gs.Attr.u & 0xf00));
6322 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6323 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6324 || !(pCtx->gs.Attr.n.u1Granularity));
6325 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6326 || (pCtx->gs.Attr.n.u1Granularity));
6327 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6328 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6329 }
6330 /* 64-bit capable CPUs. */
6331 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6332 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6333 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6334 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6335 }
6336 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6337 || ( CPUMIsGuestInRealModeEx(pCtx)
6338 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6339 {
6340 /* Real and v86 mode checks. */
6341 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6342 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6343 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6344 {
6345 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6346 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6347 }
6348 else
6349 {
6350 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6351 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6352 }
6353
6354 /* CS */
6355 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6356 Assert(pCtx->cs.u32Limit == 0xffff);
6357 Assert(u32CSAttr == 0xf3);
6358 /* SS */
6359 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6360 Assert(pCtx->ss.u32Limit == 0xffff);
6361 Assert(u32SSAttr == 0xf3);
6362 /* DS */
6363 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6364 Assert(pCtx->ds.u32Limit == 0xffff);
6365 Assert(u32DSAttr == 0xf3);
6366 /* ES */
6367 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6368 Assert(pCtx->es.u32Limit == 0xffff);
6369 Assert(u32ESAttr == 0xf3);
6370 /* FS */
6371 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6372 Assert(pCtx->fs.u32Limit == 0xffff);
6373 Assert(u32FSAttr == 0xf3);
6374 /* GS */
6375 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6376 Assert(pCtx->gs.u32Limit == 0xffff);
6377 Assert(u32GSAttr == 0xf3);
6378 /* 64-bit capable CPUs. */
6379 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6380 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6381 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6382 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6383 }
6384}
6385#endif /* VBOX_STRICT */
6386
6387
6388/**
6389 * Exports a guest segment register into the guest-state area in the VMCS.
6390 *
6391 * @returns VBox status code.
6392 * @param pVCpu The cross context virtual CPU structure.
6393 * @param pVmcsInfo The VMCS info. object.
6394 * @param iSegReg The segment register number (X86_SREG_XXX).
6395 * @param pSelReg Pointer to the segment selector.
6396 *
6397 * @remarks No-long-jump zone!!!
6398 */
6399static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint32_t iSegReg, PCCPUMSELREG pSelReg)
6400{
6401 Assert(iSegReg < X86_SREG_COUNT);
6402
6403 uint32_t u32Access = pSelReg->Attr.u;
6404 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
6405 {
6406 /*
6407 * The way to differentiate between whether this is really a null selector or was just
6408 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6409 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6410 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6411 * NULL selectors loaded in protected-mode have their attribute as 0.
6412 */
6413 if (u32Access)
6414 { }
6415 else
6416 u32Access = X86DESCATTR_UNUSABLE;
6417 }
6418 else
6419 {
6420 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6421 u32Access = 0xf3;
6422 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6423 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6424 RT_NOREF_PV(pVCpu);
6425 }
6426
6427 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6428 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6429 ("Access bit not set for usable segment. %.2s sel=%#x attr %#x\n", "ESCSSSDSFSGS" + iSegReg * 2, pSelReg, pSelReg->Attr.u));
6430
6431 /*
6432 * Commit it to the VMCS.
6433 */
6434 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
6435 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
6436 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
6437 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
6438 int rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), pSelReg->Sel); AssertRC(rc);
6439 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), pSelReg->u32Limit); AssertRC(rc);
6440 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), pSelReg->u64Base); AssertRC(rc);
6441 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), u32Access); AssertRC(rc);
6442 return VINF_SUCCESS;
6443}
6444
6445
6446/**
6447 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6448 * area in the VMCS.
6449 *
6450 * @returns VBox status code.
6451 * @param pVCpu The cross context virtual CPU structure.
6452 * @param pVmxTransient The VMX-transient structure.
6453 *
6454 * @remarks Will import guest CR0 on strict builds during validation of
6455 * segments.
6456 * @remarks No-long-jump zone!!!
6457 */
6458static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6459{
6460 int rc = VERR_INTERNAL_ERROR_5;
6461 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6462 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6463 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6464 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
6465
6466 /*
6467 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6468 */
6469 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6470 {
6471 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6472 {
6473 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6474 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6475 pVmcsInfoShared->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6476 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6477 AssertRC(rc);
6478 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6479 }
6480
6481 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6482 {
6483 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6484 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6485 pVmcsInfoShared->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6486 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6487 AssertRC(rc);
6488 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6489 }
6490
6491 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6492 {
6493 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6494 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6495 pVmcsInfoShared->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6496 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6497 AssertRC(rc);
6498 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6499 }
6500
6501 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6502 {
6503 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6504 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6505 pVmcsInfoShared->RealMode.AttrES.u = pCtx->es.Attr.u;
6506 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6507 AssertRC(rc);
6508 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6509 }
6510
6511 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6512 {
6513 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6514 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6515 pVmcsInfoShared->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6516 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6517 AssertRC(rc);
6518 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6519 }
6520
6521 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6522 {
6523 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6524 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
6525 pVmcsInfoShared->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6526 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6527 AssertRC(rc);
6528 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6529 }
6530
6531#ifdef VBOX_STRICT
6532 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6533#endif
6534 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6535 pCtx->cs.Attr.u));
6536 }
6537
6538 /*
6539 * Guest TR.
6540 */
6541 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6542 {
6543 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6544
6545 /*
6546 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6547 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6548 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6549 */
6550 uint16_t u16Sel;
6551 uint32_t u32Limit;
6552 uint64_t u64Base;
6553 uint32_t u32AccessRights;
6554 if (!pVmcsInfoShared->RealMode.fRealOnV86Active)
6555 {
6556 u16Sel = pCtx->tr.Sel;
6557 u32Limit = pCtx->tr.u32Limit;
6558 u64Base = pCtx->tr.u64Base;
6559 u32AccessRights = pCtx->tr.Attr.u;
6560 }
6561 else
6562 {
6563 Assert(!pVmxTransient->fIsNestedGuest);
6564 Assert(pVM->hm.s.vmx.pRealModeTSS);
6565 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6566
6567 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6568 RTGCPHYS GCPhys;
6569 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6570 AssertRCReturn(rc, rc);
6571
6572 X86DESCATTR DescAttr;
6573 DescAttr.u = 0;
6574 DescAttr.n.u1Present = 1;
6575 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6576
6577 u16Sel = 0;
6578 u32Limit = HM_VTX_TSS_SIZE;
6579 u64Base = GCPhys;
6580 u32AccessRights = DescAttr.u;
6581 }
6582
6583 /* Validate. */
6584 Assert(!(u16Sel & RT_BIT(2)));
6585 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6586 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6587 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6588 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6589 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6590 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6591 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6592 Assert( (u32Limit & 0xfff) == 0xfff
6593 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6594 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6595 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6596
6597 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6598 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6599 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6600 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6601
6602 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6603 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6604 }
6605
6606 /*
6607 * Guest GDTR.
6608 */
6609 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6610 {
6611 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6612
6613 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6614 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6615
6616 /* Validate. */
6617 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6618
6619 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6620 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6621 }
6622
6623 /*
6624 * Guest LDTR.
6625 */
6626 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6627 {
6628 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6629
6630 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6631 uint32_t u32Access;
6632 if ( !pVmxTransient->fIsNestedGuest
6633 && !pCtx->ldtr.Attr.u)
6634 u32Access = X86DESCATTR_UNUSABLE;
6635 else
6636 u32Access = pCtx->ldtr.Attr.u;
6637
6638 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6639 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6640 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6641 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6642
6643 /* Validate. */
6644 if (!(u32Access & X86DESCATTR_UNUSABLE))
6645 {
6646 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6647 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6648 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6649 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6650 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6651 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6652 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6653 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6654 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6655 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6656 }
6657
6658 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6659 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6660 }
6661
6662 /*
6663 * Guest IDTR.
6664 */
6665 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6666 {
6667 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6668
6669 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6670 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6671
6672 /* Validate. */
6673 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6674
6675 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6676 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6677 }
6678
6679 return VINF_SUCCESS;
6680}
6681
6682
6683/**
6684 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6685 * areas.
6686 *
6687 * These MSRs will automatically be loaded to the host CPU on every successful
6688 * VM-entry and stored from the host CPU on every successful VM-exit.
6689 *
6690 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6691 * actual host MSR values are not- updated here for performance reasons. See
6692 * hmR0VmxExportHostMsrs().
6693 *
6694 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6695 *
6696 * @returns VBox status code.
6697 * @param pVCpu The cross context virtual CPU structure.
6698 * @param pVmxTransient The VMX-transient structure.
6699 *
6700 * @remarks No-long-jump zone!!!
6701 */
6702static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6703{
6704 AssertPtr(pVCpu);
6705 AssertPtr(pVmxTransient);
6706
6707 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6708 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6709
6710 /*
6711 * MSRs that we use the auto-load/store MSR area in the VMCS.
6712 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6713 * nothing to do here. The host MSR values are updated when it's safe in
6714 * hmR0VmxLazySaveHostMsrs().
6715 *
6716 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6717 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6718 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6719 * for any MSR that are not part of the lazy MSRs so we do not need to place
6720 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6721 */
6722 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6723 {
6724 /* No auto-load/store MSRs currently. */
6725 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6726 }
6727
6728 /*
6729 * Guest Sysenter MSRs.
6730 */
6731 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6732 {
6733 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6734
6735 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6736 {
6737 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6738 AssertRC(rc);
6739 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6740 }
6741
6742 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6743 {
6744 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6745 AssertRC(rc);
6746 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6747 }
6748
6749 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6750 {
6751 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6752 AssertRC(rc);
6753 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6754 }
6755 }
6756
6757 /*
6758 * Guest/host EFER MSR.
6759 */
6760 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6761 {
6762 /* Whether we are using the VMCS to swap the EFER MSR must have been
6763 determined earlier while exporting VM-entry/VM-exit controls. */
6764 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6765 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6766
6767 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6768 {
6769 /*
6770 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6771 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6772 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6773 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6774 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6775 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6776 * during VM-entry.
6777 */
6778 uint64_t uGuestEferMsr = pCtx->msrEFER;
6779 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6780 {
6781 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6782 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6783 else
6784 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6785 }
6786
6787 /*
6788 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6789 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6790 */
6791 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6792 {
6793 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6794 AssertRC(rc);
6795 }
6796 else
6797 {
6798 /*
6799 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6800 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6801 */
6802 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6803 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6804 AssertRCReturn(rc, rc);
6805 }
6806
6807 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6808 }
6809 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6810 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6811
6812 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6813 }
6814
6815 /*
6816 * Other MSRs.
6817 */
6818 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6819 {
6820 /* Speculation Control (R/W). */
6821 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6822 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6823 {
6824 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6825 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6826 AssertRCReturn(rc, rc);
6827 }
6828
6829 /* Last Branch Record. */
6830 if (pVM->hm.s.vmx.fLbr)
6831 {
6832 PVMXVMCSINFOSHARED const pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
6833 uint32_t const idFromIpMsrStart = pVM->hm.s.vmx.idLbrFromIpMsrFirst;
6834 uint32_t const idToIpMsrStart = pVM->hm.s.vmx.idLbrToIpMsrFirst;
6835 uint32_t const cLbrStack = pVM->hm.s.vmx.idLbrFromIpMsrLast - pVM->hm.s.vmx.idLbrFromIpMsrFirst + 1;
6836 Assert(cLbrStack <= 32);
6837 for (uint32_t i = 0; i < cLbrStack; i++)
6838 {
6839 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idFromIpMsrStart + i,
6840 pVmcsInfoShared->au64LbrFromIpMsr[i],
6841 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6842 AssertRCReturn(rc, rc);
6843
6844 /* Some CPUs don't have a Branch-To-IP MSR (P4 and related Xeons). */
6845 if (idToIpMsrStart != 0)
6846 {
6847 rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, idToIpMsrStart + i,
6848 pVmcsInfoShared->au64LbrToIpMsr[i],
6849 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6850 AssertRCReturn(rc, rc);
6851 }
6852 }
6853
6854 /* Add LBR top-of-stack MSR (which contains the index to the most recent record). */
6855 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, pVM->hm.s.vmx.idLbrTosMsr,
6856 pVmcsInfoShared->u64LbrTosMsr, false /* fSetReadWrite */,
6857 false /* fUpdateHostMsr */);
6858 AssertRCReturn(rc, rc);
6859 }
6860
6861 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6862 }
6863
6864 return VINF_SUCCESS;
6865}
6866
6867
6868/**
6869 * Wrapper for running the guest code in VT-x.
6870 *
6871 * @returns VBox status code, no informational status codes.
6872 * @param pVCpu The cross context virtual CPU structure.
6873 * @param pVmxTransient The VMX-transient structure.
6874 *
6875 * @remarks No-long-jump zone!!!
6876 */
6877DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6878{
6879 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6880 pVCpu->cpum.GstCtx.fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6881
6882 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6883 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6884 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6885 int rc = pVCpu->hmr0.s.vmx.pfnStartVm(pVmcsInfo, pVCpu, fResumeVM);
6886 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6887 return rc;
6888}
6889
6890
6891/**
6892 * Reports world-switch error and dumps some useful debug info.
6893 *
6894 * @param pVCpu The cross context virtual CPU structure.
6895 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6896 * @param pVmxTransient The VMX-transient structure (only
6897 * exitReason updated).
6898 */
6899static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6900{
6901 Assert(pVCpu);
6902 Assert(pVmxTransient);
6903 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6904
6905 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6906 switch (rcVMRun)
6907 {
6908 case VERR_VMX_INVALID_VMXON_PTR:
6909 AssertFailed();
6910 break;
6911 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6912 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6913 {
6914 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6915 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6916 AssertRC(rc);
6917 hmR0VmxReadExitQualVmcs(pVmxTransient);
6918
6919 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
6920 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6921 Cannot do it here as we may have been long preempted. */
6922
6923#ifdef VBOX_STRICT
6924 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6925 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6926 pVmxTransient->uExitReason));
6927 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6928 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6929 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6930 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6931 else
6932 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6933 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6934 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6935
6936 static struct
6937 {
6938 /** Name of the field to log. */
6939 const char *pszName;
6940 /** The VMCS field. */
6941 uint32_t uVmcsField;
6942 /** Whether host support of this field needs to be checked. */
6943 bool fCheckSupport;
6944 } const s_aVmcsFields[] =
6945 {
6946 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6947 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6948 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6949 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6950 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6951 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6952 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6953 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6954 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6955 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6956 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6957 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6958 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6959 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6960 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6961 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6962 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6963 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6964 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6965 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6966 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6967 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6968 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6969 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6970 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6971 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6972 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6973 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6974 /* The order of selector fields below are fixed! */
6975 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6976 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6977 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6978 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6979 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6980 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6981 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6982 /* End of ordered selector fields. */
6983 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6984 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6985 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6986 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6987 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6988 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6989 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6990 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6991 };
6992
6993 RTGDTR HostGdtr;
6994 ASMGetGDTR(&HostGdtr);
6995
6996 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6997 for (uint32_t i = 0; i < cVmcsFields; i++)
6998 {
6999 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
7000
7001 bool fSupported;
7002 if (!s_aVmcsFields[i].fCheckSupport)
7003 fSupported = true;
7004 else
7005 {
7006 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7007 switch (uVmcsField)
7008 {
7009 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
7010 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
7011 case VMX_VMCS32_CTRL_PROC_EXEC2:
7012 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
7013 break;
7014 default:
7015 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
7016 }
7017 }
7018
7019 if (fSupported)
7020 {
7021 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
7022 switch (uWidth)
7023 {
7024 case VMX_VMCSFIELD_WIDTH_16BIT:
7025 {
7026 uint16_t u16Val;
7027 rc = VMXReadVmcs16(uVmcsField, &u16Val);
7028 AssertRC(rc);
7029 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
7030
7031 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
7032 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
7033 {
7034 if (u16Val < HostGdtr.cbGdt)
7035 {
7036 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
7037 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
7038 "Host FS", "Host GS", "Host TR" };
7039 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
7040 Assert(idxSel < RT_ELEMENTS(s_apszSel));
7041 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
7042 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
7043 }
7044 else
7045 Log4((" Selector value exceeds GDT limit!\n"));
7046 }
7047 break;
7048 }
7049
7050 case VMX_VMCSFIELD_WIDTH_32BIT:
7051 {
7052 uint32_t u32Val;
7053 rc = VMXReadVmcs32(uVmcsField, &u32Val);
7054 AssertRC(rc);
7055 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
7056 break;
7057 }
7058
7059 case VMX_VMCSFIELD_WIDTH_64BIT:
7060 case VMX_VMCSFIELD_WIDTH_NATURAL:
7061 {
7062 uint64_t u64Val;
7063 rc = VMXReadVmcs64(uVmcsField, &u64Val);
7064 AssertRC(rc);
7065 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
7066 break;
7067 }
7068 }
7069 }
7070 }
7071
7072 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7073 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7074 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7075 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7076 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7077 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7078#endif /* VBOX_STRICT */
7079 break;
7080 }
7081
7082 default:
7083 /* Impossible */
7084 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7085 break;
7086 }
7087}
7088
7089
7090/**
7091 * Sets up the usage of TSC-offsetting and updates the VMCS.
7092 *
7093 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7094 * VMX-preemption timer.
7095 *
7096 * @returns VBox status code.
7097 * @param pVCpu The cross context virtual CPU structure.
7098 * @param pVmxTransient The VMX-transient structure.
7099 *
7100 * @remarks No-long-jump zone!!!
7101 */
7102static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
7103{
7104 bool fOffsettedTsc;
7105 bool fParavirtTsc;
7106 uint64_t uTscOffset;
7107 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7108 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7109
7110 if (pVM->hm.s.vmx.fUsePreemptTimer)
7111 {
7112 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7113
7114 /* Make sure the returned values have sane upper and lower boundaries. */
7115 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7116 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7117 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7118 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7119
7120 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7121 * preemption timers here. We probably need to clamp the preemption timer,
7122 * after converting the timer value to the host. */
7123 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7124 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7125 AssertRC(rc);
7126 }
7127 else
7128 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7129
7130 if (fParavirtTsc)
7131 {
7132 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7133 information before every VM-entry, hence disable it for performance sake. */
7134#if 0
7135 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7136 AssertRC(rc);
7137#endif
7138 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7139 }
7140
7141 if ( fOffsettedTsc
7142 && RT_LIKELY(!pVCpu->hmr0.s.fDebugWantRdTscExit))
7143 {
7144 if (pVmxTransient->fIsNestedGuest)
7145 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7146 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
7147 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7148 }
7149 else
7150 {
7151 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7152 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7153 }
7154}
7155
7156
7157/**
7158 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7159 * VM-exit interruption info type.
7160 *
7161 * @returns The IEM exception flags.
7162 * @param uVector The event vector.
7163 * @param uVmxEventType The VMX event type.
7164 *
7165 * @remarks This function currently only constructs flags required for
7166 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7167 * and CR2 aspects of an exception are not included).
7168 */
7169static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7170{
7171 uint32_t fIemXcptFlags;
7172 switch (uVmxEventType)
7173 {
7174 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7175 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7176 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7177 break;
7178
7179 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7180 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7181 break;
7182
7183 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7184 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7185 break;
7186
7187 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7188 {
7189 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7190 if (uVector == X86_XCPT_BP)
7191 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7192 else if (uVector == X86_XCPT_OF)
7193 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7194 else
7195 {
7196 fIemXcptFlags = 0;
7197 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7198 }
7199 break;
7200 }
7201
7202 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7203 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7204 break;
7205
7206 default:
7207 fIemXcptFlags = 0;
7208 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7209 break;
7210 }
7211 return fIemXcptFlags;
7212}
7213
7214
7215/**
7216 * Sets an event as a pending event to be injected into the guest.
7217 *
7218 * @param pVCpu The cross context virtual CPU structure.
7219 * @param u32IntInfo The VM-entry interruption-information field.
7220 * @param cbInstr The VM-entry instruction length in bytes (for
7221 * software interrupts, exceptions and privileged
7222 * software exceptions).
7223 * @param u32ErrCode The VM-entry exception error code.
7224 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7225 * page-fault.
7226 */
7227DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7228 RTGCUINTPTR GCPtrFaultAddress)
7229{
7230 Assert(!pVCpu->hm.s.Event.fPending);
7231 pVCpu->hm.s.Event.fPending = true;
7232 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7233 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7234 pVCpu->hm.s.Event.cbInstr = cbInstr;
7235 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7236}
7237
7238
7239/**
7240 * Sets an external interrupt as pending-for-injection into the VM.
7241 *
7242 * @param pVCpu The cross context virtual CPU structure.
7243 * @param u8Interrupt The external interrupt vector.
7244 */
7245DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
7246{
7247 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7248 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7249 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7250 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7251 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7252}
7253
7254
7255/**
7256 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7257 *
7258 * @param pVCpu The cross context virtual CPU structure.
7259 */
7260DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
7261{
7262 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7263 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7264 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7265 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7266 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7267}
7268
7269
7270/**
7271 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7272 *
7273 * @param pVCpu The cross context virtual CPU structure.
7274 */
7275DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
7276{
7277 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7278 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7279 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7280 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7281 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7282}
7283
7284
7285/**
7286 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7287 *
7288 * @param pVCpu The cross context virtual CPU structure.
7289 */
7290DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
7291{
7292 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7293 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7294 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7295 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7296 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7297}
7298
7299
7300/**
7301 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7302 *
7303 * @param pVCpu The cross context virtual CPU structure.
7304 */
7305DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7306{
7307 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7308 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7309 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7310 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7311 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7312}
7313
7314
7315#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7316/**
7317 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7318 *
7319 * @param pVCpu The cross context virtual CPU structure.
7320 * @param u32ErrCode The error code for the general-protection exception.
7321 */
7322DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7323{
7324 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7325 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7326 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7327 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7328 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7329}
7330
7331
7332/**
7333 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7334 *
7335 * @param pVCpu The cross context virtual CPU structure.
7336 * @param u32ErrCode The error code for the stack exception.
7337 */
7338DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7339{
7340 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7341 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7342 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7343 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7344 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7345}
7346#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7347
7348
7349/**
7350 * Fixes up attributes for the specified segment register.
7351 *
7352 * @param pVCpu The cross context virtual CPU structure.
7353 * @param pSelReg The segment register that needs fixing.
7354 * @param pszRegName The register name (for logging and assertions).
7355 */
7356static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, const char *pszRegName)
7357{
7358 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7359
7360 /*
7361 * If VT-x marks the segment as unusable, most other bits remain undefined:
7362 * - For CS the L, D and G bits have meaning.
7363 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7364 * - For the remaining data segments no bits are defined.
7365 *
7366 * The present bit and the unusable bit has been observed to be set at the
7367 * same time (the selector was supposed to be invalid as we started executing
7368 * a V8086 interrupt in ring-0).
7369 *
7370 * What should be important for the rest of the VBox code, is that the P bit is
7371 * cleared. Some of the other VBox code recognizes the unusable bit, but
7372 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7373 * safe side here, we'll strip off P and other bits we don't care about. If
7374 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7375 *
7376 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7377 */
7378#ifdef VBOX_STRICT
7379 uint32_t const uAttr = pSelReg->Attr.u;
7380#endif
7381
7382 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7383 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7384 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7385
7386#ifdef VBOX_STRICT
7387 VMMRZCallRing3Disable(pVCpu);
7388 Log4Func(("Unusable %s: sel=%#x attr=%#x -> %#x\n", pszRegName, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7389# ifdef DEBUG_bird
7390 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7391 ("%s: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7392 pszRegName, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7393# endif
7394 VMMRZCallRing3Enable(pVCpu);
7395 NOREF(uAttr);
7396#endif
7397 RT_NOREF2(pVCpu, pszRegName);
7398}
7399
7400
7401/**
7402 * Imports a guest segment register from the current VMCS into the guest-CPU
7403 * context.
7404 *
7405 * @param pVCpu The cross context virtual CPU structure.
7406 * @param iSegReg The segment register number (X86_SREG_XXX).
7407 *
7408 * @remarks Called with interrupts and/or preemption disabled.
7409 */
7410static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint32_t iSegReg)
7411{
7412 Assert(iSegReg < X86_SREG_COUNT);
7413 Assert((uint32_t)VMX_VMCS16_GUEST_SEG_SEL(iSegReg) == g_aVmcsSegSel[iSegReg]);
7414 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg) == g_aVmcsSegLimit[iSegReg]);
7415 Assert((uint32_t)VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg) == g_aVmcsSegAttr[iSegReg]);
7416 Assert((uint32_t)VMX_VMCS_GUEST_SEG_BASE(iSegReg) == g_aVmcsSegBase[iSegReg]);
7417
7418 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7419
7420 uint16_t u16Sel;
7421 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_SEG_SEL(iSegReg), &u16Sel); AssertRC(rc);
7422 pSelReg->Sel = u16Sel;
7423 pSelReg->ValidSel = u16Sel;
7424
7425 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_LIMIT(iSegReg), &pSelReg->u32Limit); AssertRC(rc);
7426 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SEG_BASE(iSegReg), &pSelReg->u64Base); AssertRC(rc);
7427
7428 uint32_t u32Attr;
7429 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SEG_ACCESS_RIGHTS(iSegReg), &u32Attr); AssertRC(rc);
7430 pSelReg->Attr.u = u32Attr;
7431 if (u32Attr & X86DESCATTR_UNUSABLE)
7432 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, "ES\0CS\0SS\0DS\0FS\0GS" + iSegReg * 3);
7433
7434 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7435}
7436
7437
7438/**
7439 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7440 *
7441 * @param pVCpu The cross context virtual CPU structure.
7442 *
7443 * @remarks Called with interrupts and/or preemption disabled.
7444 */
7445static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7446{
7447 uint16_t u16Sel;
7448 uint64_t u64Base;
7449 uint32_t u32Limit, u32Attr;
7450 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7451 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7452 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7453 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7454
7455 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7456 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7457 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7458 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7459 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7460 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7461 if (u32Attr & X86DESCATTR_UNUSABLE)
7462 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, "LDTR");
7463}
7464
7465
7466/**
7467 * Imports the guest TR from the current VMCS into the guest-CPU context.
7468 *
7469 * @param pVCpu The cross context virtual CPU structure.
7470 *
7471 * @remarks Called with interrupts and/or preemption disabled.
7472 */
7473static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7474{
7475 uint16_t u16Sel;
7476 uint64_t u64Base;
7477 uint32_t u32Limit, u32Attr;
7478 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7479 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7480 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7481 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7482
7483 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7484 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7485 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7486 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7487 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7488 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7489 /* TR is the only selector that can never be unusable. */
7490 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7491}
7492
7493
7494/**
7495 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7496 *
7497 * @param pVCpu The cross context virtual CPU structure.
7498 *
7499 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7500 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7501 * instead!!!
7502 */
7503static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7504{
7505 uint64_t u64Val;
7506 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7507 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7508 {
7509 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7510 AssertRC(rc);
7511
7512 pCtx->rip = u64Val;
7513 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7514 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7515 }
7516}
7517
7518
7519/**
7520 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7521 *
7522 * @param pVCpu The cross context virtual CPU structure.
7523 * @param pVmcsInfo The VMCS info. object.
7524 *
7525 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7526 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7527 * instead!!!
7528 */
7529static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7530{
7531 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7532 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7533 {
7534 uint64_t u64Val;
7535 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7536 AssertRC(rc);
7537
7538 pCtx->rflags.u64 = u64Val;
7539 PCVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7540 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
7541 {
7542 pCtx->eflags.Bits.u1VM = 0;
7543 pCtx->eflags.Bits.u2IOPL = pVmcsInfoShared->RealMode.Eflags.Bits.u2IOPL;
7544 }
7545 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7546 }
7547}
7548
7549
7550/**
7551 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7552 * context.
7553 *
7554 * @param pVCpu The cross context virtual CPU structure.
7555 * @param pVmcsInfo The VMCS info. object.
7556 *
7557 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7558 * do not log!
7559 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7560 * instead!!!
7561 */
7562static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7563{
7564 uint32_t u32Val;
7565 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7566 if (!u32Val)
7567 {
7568 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7569 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7570 CPUMSetGuestNmiBlocking(pVCpu, false);
7571 }
7572 else
7573 {
7574 /*
7575 * We must import RIP here to set our EM interrupt-inhibited state.
7576 * We also import RFLAGS as our code that evaluates pending interrupts
7577 * before VM-entry requires it.
7578 */
7579 hmR0VmxImportGuestRip(pVCpu);
7580 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7581
7582 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7583 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7584 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7585 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7586
7587 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7588 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7589 }
7590}
7591
7592
7593/**
7594 * Worker for VMXR0ImportStateOnDemand.
7595 *
7596 * @returns VBox status code.
7597 * @param pVCpu The cross context virtual CPU structure.
7598 * @param pVmcsInfo The VMCS info. object.
7599 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7600 */
7601static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7602{
7603 int rc = VINF_SUCCESS;
7604 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7605 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7606 uint32_t u32Val;
7607
7608 /*
7609 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7610 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7611 * neither are other host platforms.
7612 *
7613 * Committing this temporarily as it prevents BSOD.
7614 *
7615 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7616 */
7617#ifdef RT_OS_WINDOWS
7618 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7619 return VERR_HM_IPE_1;
7620#endif
7621
7622 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7623
7624 /*
7625 * We disable interrupts to make the updating of the state and in particular
7626 * the fExtrn modification atomic wrt to preemption hooks.
7627 */
7628 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7629
7630 fWhat &= pCtx->fExtrn;
7631 if (fWhat)
7632 {
7633 do
7634 {
7635 if (fWhat & CPUMCTX_EXTRN_RIP)
7636 hmR0VmxImportGuestRip(pVCpu);
7637
7638 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7639 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7640
7641 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7642 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7643
7644 if (fWhat & CPUMCTX_EXTRN_RSP)
7645 {
7646 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7647 AssertRC(rc);
7648 }
7649
7650 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7651 {
7652 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7653 bool const fRealOnV86Active = pVmcsInfoShared->RealMode.fRealOnV86Active;
7654 if (fWhat & CPUMCTX_EXTRN_CS)
7655 {
7656 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7657 hmR0VmxImportGuestRip(pVCpu);
7658 if (fRealOnV86Active)
7659 pCtx->cs.Attr.u = pVmcsInfoShared->RealMode.AttrCS.u;
7660 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7661 }
7662 if (fWhat & CPUMCTX_EXTRN_SS)
7663 {
7664 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7665 if (fRealOnV86Active)
7666 pCtx->ss.Attr.u = pVmcsInfoShared->RealMode.AttrSS.u;
7667 }
7668 if (fWhat & CPUMCTX_EXTRN_DS)
7669 {
7670 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7671 if (fRealOnV86Active)
7672 pCtx->ds.Attr.u = pVmcsInfoShared->RealMode.AttrDS.u;
7673 }
7674 if (fWhat & CPUMCTX_EXTRN_ES)
7675 {
7676 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7677 if (fRealOnV86Active)
7678 pCtx->es.Attr.u = pVmcsInfoShared->RealMode.AttrES.u;
7679 }
7680 if (fWhat & CPUMCTX_EXTRN_FS)
7681 {
7682 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7683 if (fRealOnV86Active)
7684 pCtx->fs.Attr.u = pVmcsInfoShared->RealMode.AttrFS.u;
7685 }
7686 if (fWhat & CPUMCTX_EXTRN_GS)
7687 {
7688 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7689 if (fRealOnV86Active)
7690 pCtx->gs.Attr.u = pVmcsInfoShared->RealMode.AttrGS.u;
7691 }
7692 }
7693
7694 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7695 {
7696 if (fWhat & CPUMCTX_EXTRN_LDTR)
7697 hmR0VmxImportGuestLdtr(pVCpu);
7698
7699 if (fWhat & CPUMCTX_EXTRN_GDTR)
7700 {
7701 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7702 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7703 pCtx->gdtr.cbGdt = u32Val;
7704 }
7705
7706 /* Guest IDTR. */
7707 if (fWhat & CPUMCTX_EXTRN_IDTR)
7708 {
7709 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7710 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7711 pCtx->idtr.cbIdt = u32Val;
7712 }
7713
7714 /* Guest TR. */
7715 if (fWhat & CPUMCTX_EXTRN_TR)
7716 {
7717 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7718 don't need to import that one. */
7719 if (!pVmcsInfo->pShared->RealMode.fRealOnV86Active)
7720 hmR0VmxImportGuestTr(pVCpu);
7721 }
7722 }
7723
7724 if (fWhat & CPUMCTX_EXTRN_DR7)
7725 {
7726 if (!pVCpu->hmr0.s.fUsingHyperDR7)
7727 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7728 }
7729
7730 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7731 {
7732 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7733 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7734 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7735 pCtx->SysEnter.cs = u32Val;
7736 }
7737
7738 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7739 {
7740 if ( pVM->hm.s.fAllow64BitGuests
7741 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7742 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7743 }
7744
7745 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7746 {
7747 if ( pVM->hm.s.fAllow64BitGuests
7748 && (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7749 {
7750 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7751 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7752 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7753 }
7754 }
7755
7756 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7757 {
7758 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
7759 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7760 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7761 Assert(pMsrs);
7762 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7763 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7764 for (uint32_t i = 0; i < cMsrs; i++)
7765 {
7766 uint32_t const idMsr = pMsrs[i].u32Msr;
7767 switch (idMsr)
7768 {
7769 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7770 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7771 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7772 default:
7773 {
7774 uint32_t idxLbrMsr;
7775 if (pVM->hm.s.vmx.fLbr)
7776 {
7777 if (hmR0VmxIsLbrBranchFromMsr(pVM, idMsr, &idxLbrMsr))
7778 {
7779 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7780 pVmcsInfoShared->au64LbrFromIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7781 break;
7782 }
7783 if (hmR0VmxIsLbrBranchToMsr(pVM, idMsr, &idxLbrMsr))
7784 {
7785 Assert(idxLbrMsr < RT_ELEMENTS(pVmcsInfoShared->au64LbrFromIpMsr));
7786 pVmcsInfoShared->au64LbrToIpMsr[idxLbrMsr] = pMsrs[i].u64Value;
7787 break;
7788 }
7789 if (idMsr == pVM->hm.s.vmx.idLbrTosMsr)
7790 {
7791 pVmcsInfoShared->u64LbrTosMsr = pMsrs[i].u64Value;
7792 break;
7793 }
7794 /* Fallthru (no break) */
7795 }
7796 pCtx->fExtrn = 0;
7797 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7798 ASMSetFlags(fEFlags);
7799 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7800 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7801 }
7802 }
7803 }
7804 }
7805
7806 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7807 {
7808 if (fWhat & CPUMCTX_EXTRN_CR0)
7809 {
7810 uint64_t u64Cr0;
7811 uint64_t u64Shadow;
7812 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7813 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7814#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7815 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7816 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7817#else
7818 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7819 {
7820 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7821 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7822 }
7823 else
7824 {
7825 /*
7826 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7827 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7828 * re-construct CR0. See @bugref{9180#c95} for details.
7829 */
7830 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7831 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7832 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7833 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7834 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7835 }
7836#endif
7837 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7838 CPUMSetGuestCR0(pVCpu, u64Cr0);
7839 VMMRZCallRing3Enable(pVCpu);
7840 }
7841
7842 if (fWhat & CPUMCTX_EXTRN_CR4)
7843 {
7844 uint64_t u64Cr4;
7845 uint64_t u64Shadow;
7846 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7847 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7848#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7849 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7850 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7851#else
7852 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7853 {
7854 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7855 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7856 }
7857 else
7858 {
7859 /*
7860 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7861 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7862 * re-construct CR4. See @bugref{9180#c95} for details.
7863 */
7864 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
7865 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7866 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7867 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7868 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7869 }
7870#endif
7871 pCtx->cr4 = u64Cr4;
7872 }
7873
7874 if (fWhat & CPUMCTX_EXTRN_CR3)
7875 {
7876 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7877 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7878 || ( pVM->hm.s.fNestedPaging
7879 && CPUMIsGuestPagingEnabledEx(pCtx)))
7880 {
7881 uint64_t u64Cr3;
7882 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7883 if (pCtx->cr3 != u64Cr3)
7884 {
7885 pCtx->cr3 = u64Cr3;
7886 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7887 }
7888
7889 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7890 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7891 if (CPUMIsGuestInPAEModeEx(pCtx))
7892 {
7893 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7894 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7895 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7896 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7897 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7898 }
7899 }
7900 }
7901 }
7902
7903#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7904 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7905 {
7906 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7907 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7908 {
7909 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7910 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7911 if (RT_SUCCESS(rc))
7912 { /* likely */ }
7913 else
7914 break;
7915 }
7916 }
7917#endif
7918 } while (0);
7919
7920 if (RT_SUCCESS(rc))
7921 {
7922 /* Update fExtrn. */
7923 pCtx->fExtrn &= ~fWhat;
7924
7925 /* If everything has been imported, clear the HM keeper bit. */
7926 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7927 {
7928 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7929 Assert(!pCtx->fExtrn);
7930 }
7931 }
7932 }
7933 else
7934 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7935
7936 /*
7937 * Restore interrupts.
7938 */
7939 ASMSetFlags(fEFlags);
7940
7941 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7942
7943 if (RT_SUCCESS(rc))
7944 { /* likely */ }
7945 else
7946 return rc;
7947
7948 /*
7949 * Honor any pending CR3 updates.
7950 *
7951 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7952 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7953 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7954 *
7955 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7956 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7957 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7958 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7959 *
7960 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7961 */
7962 if (VMMRZCallRing3IsEnabled(pVCpu))
7963 {
7964 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7965 {
7966 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7967 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7968 }
7969
7970 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7971 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7972
7973 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7974 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7975 }
7976
7977 return VINF_SUCCESS;
7978}
7979
7980
7981/**
7982 * Saves the guest state from the VMCS into the guest-CPU context.
7983 *
7984 * @returns VBox status code.
7985 * @param pVCpu The cross context virtual CPU structure.
7986 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7987 */
7988VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7989{
7990 AssertPtr(pVCpu);
7991 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7992 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7993}
7994
7995
7996/**
7997 * Check per-VM and per-VCPU force flag actions that require us to go back to
7998 * ring-3 for one reason or another.
7999 *
8000 * @returns Strict VBox status code (i.e. informational status codes too)
8001 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8002 * ring-3.
8003 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8004 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8005 * interrupts)
8006 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8007 * all EMTs to be in ring-3.
8008 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8009 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8010 * to the EM loop.
8011 *
8012 * @param pVCpu The cross context virtual CPU structure.
8013 * @param pVmxTransient The VMX-transient structure.
8014 * @param fStepping Whether we are single-stepping the guest using the
8015 * hypervisor debugger.
8016 *
8017 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
8018 * is no longer in VMX non-root mode.
8019 */
8020static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, bool fStepping)
8021{
8022 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8023
8024 /*
8025 * Update pending interrupts into the APIC's IRR.
8026 */
8027 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8028 APICUpdatePendingInterrupts(pVCpu);
8029
8030 /*
8031 * Anything pending? Should be more likely than not if we're doing a good job.
8032 */
8033 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8034 if ( !fStepping
8035 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8036 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8037 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8038 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8039 return VINF_SUCCESS;
8040
8041 /* Pending PGM C3 sync. */
8042 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8043 {
8044 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8045 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8046 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8047 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8048 if (rcStrict != VINF_SUCCESS)
8049 {
8050 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
8051 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
8052 return rcStrict;
8053 }
8054 }
8055
8056 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8057 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8058 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8059 {
8060 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8061 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8062 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
8063 return rc;
8064 }
8065
8066 /* Pending VM request packets, such as hardware interrupts. */
8067 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8068 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8069 {
8070 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8071 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8072 return VINF_EM_PENDING_REQUEST;
8073 }
8074
8075 /* Pending PGM pool flushes. */
8076 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8077 {
8078 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8079 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8080 return VINF_PGM_POOL_FLUSH_PENDING;
8081 }
8082
8083 /* Pending DMA requests. */
8084 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8085 {
8086 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8087 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8088 return VINF_EM_RAW_TO_R3;
8089 }
8090
8091#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8092 /*
8093 * Pending nested-guest events.
8094 *
8095 * Please note the priority of these events are specified and important.
8096 * See Intel spec. 29.4.3.2 "APIC-Write Emulation".
8097 * See Intel spec. 6.9 "Priority Among Simultaneous Exceptions And Interrupts".
8098 */
8099 if (pVmxTransient->fIsNestedGuest)
8100 {
8101 /* Pending nested-guest APIC-write. */
8102 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
8103 {
8104 Log4Func(("Pending nested-guest APIC-write\n"));
8105 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
8106 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8107 return rcStrict;
8108 }
8109
8110 /* Pending nested-guest monitor-trap flag (MTF). */
8111 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_MTF))
8112 {
8113 Log4Func(("Pending nested-guest MTF\n"));
8114 VBOXSTRICTRC rcStrict = IEMExecVmxVmexit(pVCpu, VMX_EXIT_MTF, 0 /* uExitQual */);
8115 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8116 return rcStrict;
8117 }
8118
8119 /* Pending nested-guest VMX-preemption timer expired. */
8120 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_PREEMPT_TIMER))
8121 {
8122 Log4Func(("Pending nested-guest MTF\n"));
8123 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitPreemptTimer(pVCpu);
8124 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8125 return rcStrict;
8126 }
8127 }
8128#else
8129 NOREF(pVmxTransient);
8130#endif
8131
8132 return VINF_SUCCESS;
8133}
8134
8135
8136/**
8137 * Converts any TRPM trap into a pending HM event. This is typically used when
8138 * entering from ring-3 (not longjmp returns).
8139 *
8140 * @param pVCpu The cross context virtual CPU structure.
8141 */
8142static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
8143{
8144 Assert(TRPMHasTrap(pVCpu));
8145 Assert(!pVCpu->hm.s.Event.fPending);
8146
8147 uint8_t uVector;
8148 TRPMEVENT enmTrpmEvent;
8149 uint32_t uErrCode;
8150 RTGCUINTPTR GCPtrFaultAddress;
8151 uint8_t cbInstr;
8152 bool fIcebp;
8153
8154 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
8155 AssertRC(rc);
8156
8157 uint32_t u32IntInfo;
8158 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8159 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
8160
8161 rc = TRPMResetTrap(pVCpu);
8162 AssertRC(rc);
8163 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8164 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8165
8166 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8167}
8168
8169
8170/**
8171 * Converts the pending HM event into a TRPM trap.
8172 *
8173 * @param pVCpu The cross context virtual CPU structure.
8174 */
8175static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
8176{
8177 Assert(pVCpu->hm.s.Event.fPending);
8178
8179 /* If a trap was already pending, we did something wrong! */
8180 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8181
8182 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8183 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8184 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8185
8186 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8187
8188 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8189 AssertRC(rc);
8190
8191 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8192 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8193
8194 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8195 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8196 else
8197 {
8198 uint8_t const uVectorType = VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo);
8199 switch (uVectorType)
8200 {
8201 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
8202 TRPMSetTrapDueToIcebp(pVCpu);
8203 RT_FALL_THRU();
8204 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
8205 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
8206 {
8207 AssertMsg( uVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
8208 || ( uVector == X86_XCPT_BP /* INT3 */
8209 || uVector == X86_XCPT_OF /* INTO */
8210 || uVector == X86_XCPT_DB /* INT1 (ICEBP) */),
8211 ("Invalid vector: uVector=%#x uVectorType=%#x\n", uVector, uVectorType));
8212 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8213 break;
8214 }
8215 }
8216 }
8217
8218 /* We're now done converting the pending event. */
8219 pVCpu->hm.s.Event.fPending = false;
8220}
8221
8222
8223/**
8224 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8225 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8226 *
8227 * @param pVCpu The cross context virtual CPU structure.
8228 * @param pVmcsInfo The VMCS info. object.
8229 */
8230static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8231{
8232 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8233 {
8234 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8235 {
8236 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8237 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8238 AssertRC(rc);
8239 }
8240 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8241}
8242
8243
8244/**
8245 * Clears the interrupt-window exiting control in the VMCS.
8246 *
8247 * @param pVmcsInfo The VMCS info. object.
8248 */
8249DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8250{
8251 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8252 {
8253 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8254 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8255 AssertRC(rc);
8256 }
8257}
8258
8259
8260/**
8261 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8262 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8263 *
8264 * @param pVCpu The cross context virtual CPU structure.
8265 * @param pVmcsInfo The VMCS info. object.
8266 */
8267static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
8268{
8269 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8270 {
8271 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8272 {
8273 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8274 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8275 AssertRC(rc);
8276 Log4Func(("Setup NMI-window exiting\n"));
8277 }
8278 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8279}
8280
8281
8282/**
8283 * Clears the NMI-window exiting control in the VMCS.
8284 *
8285 * @param pVmcsInfo The VMCS info. object.
8286 */
8287DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8288{
8289 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8290 {
8291 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8292 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8293 AssertRC(rc);
8294 }
8295}
8296
8297
8298/**
8299 * Does the necessary state syncing before returning to ring-3 for any reason
8300 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8301 *
8302 * @returns VBox status code.
8303 * @param pVCpu The cross context virtual CPU structure.
8304 * @param fImportState Whether to import the guest state from the VMCS back
8305 * to the guest-CPU context.
8306 *
8307 * @remarks No-long-jmp zone!!!
8308 */
8309static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
8310{
8311 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8312 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8313
8314 RTCPUID const idCpu = RTMpCpuId();
8315 Log4Func(("HostCpuId=%u\n", idCpu));
8316
8317 /*
8318 * !!! IMPORTANT !!!
8319 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
8320 */
8321
8322 /* Save the guest state if necessary. */
8323 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8324 if (fImportState)
8325 {
8326 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8327 AssertRCReturn(rc, rc);
8328 }
8329
8330 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8331 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8332 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8333
8334 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8335#ifdef VBOX_STRICT
8336 if (CPUMIsHyperDebugStateActive(pVCpu))
8337 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8338#endif
8339 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8340 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
8341 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
8342
8343 /* Restore host-state bits that VT-x only restores partially. */
8344 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8345 {
8346 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hmr0.s.vmx.fRestoreHostFlags, idCpu));
8347 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8348 }
8349 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8350
8351 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8352 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8353 {
8354 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8355 if (!fImportState)
8356 {
8357 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8358 AssertRCReturn(rc, rc);
8359 }
8360 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8361 Assert(!pVCpu->hmr0.s.vmx.fLazyMsrs);
8362 }
8363 else
8364 pVCpu->hmr0.s.vmx.fLazyMsrs = 0;
8365
8366 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8367 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8368
8369 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8370 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8371 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8372 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8373 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8374 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8375 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8376 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8377 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8378 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8379
8380 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8381
8382 /** @todo This partially defeats the purpose of having preemption hooks.
8383 * The problem is, deregistering the hooks should be moved to a place that
8384 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8385 * context.
8386 */
8387 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8388 AssertRCReturn(rc, rc);
8389
8390#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8391 /*
8392 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8393 * clear a shadow VMCS before allowing that VMCS to become active on another
8394 * logical processor. We may or may not be importing guest state which clears
8395 * it, so cover for it here.
8396 *
8397 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8398 */
8399 if ( pVmcsInfo->pvShadowVmcs
8400 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8401 {
8402 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8403 AssertRCReturn(rc, rc);
8404 }
8405
8406 /*
8407 * Flag that we need to re-export the host state if we switch to this VMCS before
8408 * executing guest or nested-guest code.
8409 */
8410 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8411#endif
8412
8413 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8414 NOREF(idCpu);
8415 return VINF_SUCCESS;
8416}
8417
8418
8419/**
8420 * Leaves the VT-x session.
8421 *
8422 * @returns VBox status code.
8423 * @param pVCpu The cross context virtual CPU structure.
8424 *
8425 * @remarks No-long-jmp zone!!!
8426 */
8427static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8428{
8429 HM_DISABLE_PREEMPT(pVCpu);
8430 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8431 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8432 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8433
8434 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8435 and done this from the VMXR0ThreadCtxCallback(). */
8436 if (!pVCpu->hmr0.s.fLeaveDone)
8437 {
8438 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8439 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8440 pVCpu->hmr0.s.fLeaveDone = true;
8441 }
8442 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8443
8444 /*
8445 * !!! IMPORTANT !!!
8446 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8447 */
8448
8449 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8450 /** @todo Deregistering here means we need to VMCLEAR always
8451 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8452 * for calling VMMR0ThreadCtxHookDisable here! */
8453 VMMR0ThreadCtxHookDisable(pVCpu);
8454
8455 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8456 int rc = HMR0LeaveCpu(pVCpu);
8457 HM_RESTORE_PREEMPT();
8458 return rc;
8459}
8460
8461
8462/**
8463 * Does the necessary state syncing before doing a longjmp to ring-3.
8464 *
8465 * @returns VBox status code.
8466 * @param pVCpu The cross context virtual CPU structure.
8467 *
8468 * @remarks No-long-jmp zone!!!
8469 */
8470DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8471{
8472 return hmR0VmxLeaveSession(pVCpu);
8473}
8474
8475
8476/**
8477 * Take necessary actions before going back to ring-3.
8478 *
8479 * An action requires us to go back to ring-3. This function does the necessary
8480 * steps before we can safely return to ring-3. This is not the same as longjmps
8481 * to ring-3, this is voluntary and prepares the guest so it may continue
8482 * executing outside HM (recompiler/IEM).
8483 *
8484 * @returns VBox status code.
8485 * @param pVCpu The cross context virtual CPU structure.
8486 * @param rcExit The reason for exiting to ring-3. Can be
8487 * VINF_VMM_UNKNOWN_RING3_CALL.
8488 */
8489static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8490{
8491 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8492
8493 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8494 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8495 {
8496 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8497 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8498 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hmr0.s.idEnteredCpu;
8499 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8500 }
8501
8502 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8503 VMMRZCallRing3Disable(pVCpu);
8504 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8505
8506 /*
8507 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8508 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8509 *
8510 * This is because execution may continue from ring-3 and we would need to inject
8511 * the event from there (hence place it back in TRPM).
8512 */
8513 if (pVCpu->hm.s.Event.fPending)
8514 {
8515 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8516 Assert(!pVCpu->hm.s.Event.fPending);
8517
8518 /* Clear the events from the VMCS. */
8519 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0); AssertRC(rc);
8520 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, 0); AssertRC(rc);
8521 }
8522#ifdef VBOX_STRICT
8523 /*
8524 * We check for rcExit here since for errors like VERR_VMX_UNABLE_TO_START_VM (which are
8525 * fatal), we don't care about verifying duplicate injection of events. Errors like
8526 * VERR_EM_INTERPRET are converted to their VINF_* counterparts -prior- to calling this
8527 * function so those should and will be checked below.
8528 */
8529 else if (RT_SUCCESS(rcExit))
8530 {
8531 /*
8532 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8533 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8534 * occasionally, see @bugref{9180#c42}.
8535 *
8536 * However, if the VM-entry failed, any VM entry-interruption info. field would
8537 * be left unmodified as the event would not have been injected to the guest. In
8538 * such cases, don't assert, we're not going to continue guest execution anyway.
8539 */
8540 uint32_t uExitReason;
8541 uint32_t uEntryIntInfo;
8542 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8543 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8544 AssertRC(rc);
8545 AssertMsg(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo),
8546 ("uExitReason=%#RX32 uEntryIntInfo=%#RX32 rcExit=%d\n", uExitReason, uEntryIntInfo, VBOXSTRICTRC_VAL(rcExit)));
8547 }
8548#endif
8549
8550 /*
8551 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8552 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8553 * (e.g. TPR below threshold).
8554 */
8555 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8556 {
8557 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8558 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8559 }
8560
8561 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8562 and if we're injecting an event we should have a TRPM trap pending. */
8563 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8564#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8565 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8566#endif
8567
8568 /* Save guest state and restore host state bits. */
8569 int rc = hmR0VmxLeaveSession(pVCpu);
8570 AssertRCReturn(rc, rc);
8571 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8572
8573 /* Thread-context hooks are unregistered at this point!!! */
8574 /* Ring-3 callback notifications are unregistered at this point!!! */
8575
8576 /* Sync recompiler state. */
8577 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8578 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8579 | CPUM_CHANGED_LDTR
8580 | CPUM_CHANGED_GDTR
8581 | CPUM_CHANGED_IDTR
8582 | CPUM_CHANGED_TR
8583 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8584 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8585 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8586 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8587
8588 Assert(!pVCpu->hmr0.s.fClearTrapFlag);
8589
8590 /* Update the exit-to-ring 3 reason. */
8591 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8592
8593 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8594 if ( rcExit != VINF_EM_RAW_INTERRUPT
8595 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8596 {
8597 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8598 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8599 }
8600
8601 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8602 VMMRZCallRing3Enable(pVCpu);
8603 return rc;
8604}
8605
8606
8607/**
8608 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8609 * longjump to ring-3 and possibly get preempted.
8610 *
8611 * @returns VBox status code.
8612 * @param pVCpu The cross context virtual CPU structure.
8613 * @param enmOperation The operation causing the ring-3 longjump.
8614 */
8615VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8616{
8617 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8618 {
8619 /*
8620 * !!! IMPORTANT !!!
8621 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8622 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8623 */
8624 VMMRZCallRing3RemoveNotification(pVCpu);
8625 VMMRZCallRing3Disable(pVCpu);
8626 HM_DISABLE_PREEMPT(pVCpu);
8627
8628 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8629 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8630 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8631 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8632
8633 /* Restore host-state bits that VT-x only restores partially. */
8634 if (pVCpu->hmr0.s.vmx.fRestoreHostFlags > VMX_RESTORE_HOST_REQUIRED)
8635 VMXRestoreHostState(pVCpu->hmr0.s.vmx.fRestoreHostFlags, &pVCpu->hmr0.s.vmx.RestoreHost);
8636 pVCpu->hmr0.s.vmx.fRestoreHostFlags = 0;
8637
8638 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8639 if (pVCpu->hmr0.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8640 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8641
8642 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8643 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = false;
8644 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8645
8646 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8647 cleared as part of importing the guest state above. */
8648 hmR0VmxClearVmcs(pVmcsInfo);
8649
8650 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8651 VMMR0ThreadCtxHookDisable(pVCpu);
8652
8653 /* Leave HM context. This takes care of local init (term). */
8654 HMR0LeaveCpu(pVCpu);
8655 HM_RESTORE_PREEMPT();
8656 return VINF_SUCCESS;
8657 }
8658
8659 Assert(pVCpu);
8660 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8661 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8662
8663 VMMRZCallRing3Disable(pVCpu);
8664 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8665
8666 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8667
8668 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8669 AssertRCReturn(rc, rc);
8670
8671 VMMRZCallRing3Enable(pVCpu);
8672 return VINF_SUCCESS;
8673}
8674
8675
8676/**
8677 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8678 * stack.
8679 *
8680 * @returns Strict VBox status code (i.e. informational status codes too).
8681 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8682 * @param pVCpu The cross context virtual CPU structure.
8683 * @param uValue The value to push to the guest stack.
8684 */
8685static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8686{
8687 /*
8688 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8689 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8690 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8691 */
8692 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8693 if (pCtx->sp == 1)
8694 return VINF_EM_RESET;
8695 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8696 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8697 AssertRC(rc);
8698 return rc;
8699}
8700
8701
8702/**
8703 * Injects an event into the guest upon VM-entry by updating the relevant fields
8704 * in the VM-entry area in the VMCS.
8705 *
8706 * @returns Strict VBox status code (i.e. informational status codes too).
8707 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8708 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8709 *
8710 * @param pVCpu The cross context virtual CPU structure.
8711 * @param pVmxTransient The VMX-transient structure.
8712 * @param pEvent The event being injected.
8713 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8714 * will be updated if necessary. This cannot not be NULL.
8715 * @param fStepping Whether we're single-stepping guest execution and should
8716 * return VINF_EM_DBG_STEPPED if the event is injected
8717 * directly (registers modified by us, not by hardware on
8718 * VM-entry).
8719 */
8720static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8721 uint32_t *pfIntrState)
8722{
8723 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8724 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8725 Assert(pfIntrState);
8726
8727 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8728 uint32_t u32IntInfo = pEvent->u64IntInfo;
8729 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8730 uint32_t const cbInstr = pEvent->cbInstr;
8731 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8732 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8733 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8734
8735#ifdef VBOX_STRICT
8736 /*
8737 * Validate the error-code-valid bit for hardware exceptions.
8738 * No error codes for exceptions in real-mode.
8739 *
8740 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8741 */
8742 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8743 && !CPUMIsGuestInRealModeEx(pCtx))
8744 {
8745 switch (uVector)
8746 {
8747 case X86_XCPT_PF:
8748 case X86_XCPT_DF:
8749 case X86_XCPT_TS:
8750 case X86_XCPT_NP:
8751 case X86_XCPT_SS:
8752 case X86_XCPT_GP:
8753 case X86_XCPT_AC:
8754 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8755 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8756 RT_FALL_THRU();
8757 default:
8758 break;
8759 }
8760 }
8761
8762 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8763 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8764 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8765#endif
8766
8767 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8768 || uIntType == VMX_EXIT_INT_INFO_TYPE_NMI
8769 || uIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT
8770 || uIntType == VMX_EXIT_INT_INFO_TYPE_SW_XCPT)
8771 {
8772 Assert(uVector <= X86_XCPT_LAST);
8773 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_NMI || uVector == X86_XCPT_NMI);
8774 Assert(uIntType != VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT || uVector == X86_XCPT_DB);
8775 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedXcptsR0[uVector]);
8776 }
8777 else
8778 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8779
8780 /*
8781 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8782 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8783 * interrupt handler in the (real-mode) guest.
8784 *
8785 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8786 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8787 */
8788 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8789 {
8790 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8791 {
8792 /*
8793 * For CPUs with unrestricted guest execution enabled and with the guest
8794 * in real-mode, we must not set the deliver-error-code bit.
8795 *
8796 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8797 */
8798 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8799 }
8800 else
8801 {
8802 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8803 Assert(PDMVmmDevHeapIsEnabled(pVM));
8804 Assert(pVM->hm.s.vmx.pRealModeTSS);
8805 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8806
8807 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8808 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8809 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8810 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8811 AssertRCReturn(rc2, rc2);
8812
8813 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8814 size_t const cbIdtEntry = sizeof(X86IDTR16);
8815 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8816 {
8817 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8818 if (uVector == X86_XCPT_DF)
8819 return VINF_EM_RESET;
8820
8821 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8822 No error codes for exceptions in real-mode. */
8823 if (uVector == X86_XCPT_GP)
8824 {
8825 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8826 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8827 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8828 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8829 HMEVENT EventXcptDf;
8830 RT_ZERO(EventXcptDf);
8831 EventXcptDf.u64IntInfo = uXcptDfInfo;
8832 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8833 }
8834
8835 /*
8836 * If we're injecting an event with no valid IDT entry, inject a #GP.
8837 * No error codes for exceptions in real-mode.
8838 *
8839 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8840 */
8841 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8842 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8843 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8844 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8845 HMEVENT EventXcptGp;
8846 RT_ZERO(EventXcptGp);
8847 EventXcptGp.u64IntInfo = uXcptGpInfo;
8848 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8849 }
8850
8851 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8852 uint16_t uGuestIp = pCtx->ip;
8853 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8854 {
8855 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8856 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8857 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8858 }
8859 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8860 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8861
8862 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8863 X86IDTR16 IdtEntry;
8864 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8865 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8866 AssertRCReturn(rc2, rc2);
8867
8868 /* Construct the stack frame for the interrupt/exception handler. */
8869 VBOXSTRICTRC rcStrict;
8870 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8871 if (rcStrict == VINF_SUCCESS)
8872 {
8873 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8874 if (rcStrict == VINF_SUCCESS)
8875 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8876 }
8877
8878 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8879 if (rcStrict == VINF_SUCCESS)
8880 {
8881 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8882 pCtx->rip = IdtEntry.offSel;
8883 pCtx->cs.Sel = IdtEntry.uSel;
8884 pCtx->cs.ValidSel = IdtEntry.uSel;
8885 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8886 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8887 && uVector == X86_XCPT_PF)
8888 pCtx->cr2 = GCPtrFault;
8889
8890 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8891 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8892 | HM_CHANGED_GUEST_RSP);
8893
8894 /*
8895 * If we delivered a hardware exception (other than an NMI) and if there was
8896 * block-by-STI in effect, we should clear it.
8897 */
8898 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8899 {
8900 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8901 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8902 Log4Func(("Clearing inhibition due to STI\n"));
8903 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8904 }
8905
8906 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8907 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8908
8909 /*
8910 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8911 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8912 */
8913 pVCpu->hm.s.Event.fPending = false;
8914
8915 /*
8916 * If we eventually support nested-guest execution without unrestricted guest execution,
8917 * we should set fInterceptEvents here.
8918 */
8919 Assert(!pVmxTransient->fIsNestedGuest);
8920
8921 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8922 if (fStepping)
8923 rcStrict = VINF_EM_DBG_STEPPED;
8924 }
8925 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8926 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8927 return rcStrict;
8928 }
8929 }
8930
8931 /*
8932 * Validate.
8933 */
8934 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8935 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8936
8937 /*
8938 * Inject the event into the VMCS.
8939 */
8940 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8941 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8942 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8943 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8944 AssertRC(rc);
8945
8946 /*
8947 * Update guest CR2 if this is a page-fault.
8948 */
8949 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8950 pCtx->cr2 = GCPtrFault;
8951
8952 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8953 return VINF_SUCCESS;
8954}
8955
8956
8957/**
8958 * Evaluates the event to be delivered to the guest and sets it as the pending
8959 * event.
8960 *
8961 * Toggling of interrupt force-flags here is safe since we update TRPM on premature
8962 * exits to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must
8963 * NOT restore these force-flags.
8964 *
8965 * @returns Strict VBox status code (i.e. informational status codes too).
8966 * @param pVCpu The cross context virtual CPU structure.
8967 * @param pVmxTransient The VMX-transient structure.
8968 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8969 */
8970static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8971{
8972 Assert(pfIntrState);
8973 Assert(!TRPMHasTrap(pVCpu));
8974
8975 /*
8976 * Compute/update guest-interruptibility state related FFs.
8977 * The FFs will be used below while evaluating events to be injected.
8978 */
8979 *pfIntrState = hmR0VmxGetGuestIntrStateAndUpdateFFs(pVCpu);
8980
8981 /*
8982 * Evaluate if a new event needs to be injected.
8983 * An event that's already pending has already performed all necessary checks.
8984 */
8985 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8986 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8987 if ( !pVCpu->hm.s.Event.fPending
8988 && !VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8989 {
8990 /** @todo SMI. SMIs take priority over NMIs. */
8991
8992 /*
8993 * NMIs.
8994 * NMIs take priority over external interrupts.
8995 */
8996 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8997 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8998 {
8999 /*
9000 * For a guest, the FF always indicates the guest's ability to receive an NMI.
9001 *
9002 * For a nested-guest, the FF always indicates the outer guest's ability to
9003 * receive an NMI while the guest-interruptibility state bit depends on whether
9004 * the nested-hypervisor is using virtual-NMIs.
9005 */
9006 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_BLOCK_NMIS))
9007 {
9008#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9009 if ( fIsNestedGuest
9010 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_NMI_EXIT))
9011 return IEMExecVmxVmexitXcptNmi(pVCpu);
9012#endif
9013 hmR0VmxSetPendingXcptNmi(pVCpu);
9014 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9015 Log4Func(("NMI pending injection\n"));
9016
9017 /* We've injected the NMI, bail. */
9018 return VINF_SUCCESS;
9019 }
9020 else if (!fIsNestedGuest)
9021 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9022 }
9023
9024 /*
9025 * External interrupts (PIC/APIC).
9026 * Once PDMGetInterrupt() returns a valid interrupt we -must- deliver it.
9027 * We cannot re-request the interrupt from the controller again.
9028 */
9029 if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9030 && !pVCpu->hm.s.fSingleInstruction)
9031 {
9032 Assert(!DBGFIsStepping(pVCpu));
9033 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9034 AssertRC(rc);
9035
9036 /*
9037 * We must not check EFLAGS directly when executing a nested-guest, use
9038 * CPUMIsGuestPhysIntrEnabled() instead as EFLAGS.IF does not control the blocking of
9039 * external interrupts when "External interrupt exiting" is set. This fixes a nasty
9040 * SMP hang while executing nested-guest VCPUs on spinlocks which aren't rescued by
9041 * other VM-exits (like a preemption timer), see @bugref{9562#c18}.
9042 *
9043 * See Intel spec. 25.4.1 "Event Blocking".
9044 */
9045 if (CPUMIsGuestPhysIntrEnabled(pVCpu))
9046 {
9047#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9048 if ( fIsNestedGuest
9049 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9050 {
9051 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9052 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9053 return rcStrict;
9054 }
9055#endif
9056 uint8_t u8Interrupt;
9057 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9058 if (RT_SUCCESS(rc))
9059 {
9060#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9061 if ( fIsNestedGuest
9062 && CPUMIsGuestVmxPinCtlsSet(pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9063 {
9064 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9065 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9066 return rcStrict;
9067 }
9068#endif
9069 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9070 Log4Func(("External interrupt (%#x) pending injection\n", u8Interrupt));
9071 }
9072 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9073 {
9074 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9075
9076 if ( !fIsNestedGuest
9077 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9078 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
9079 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9080
9081 /*
9082 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9083 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9084 * need to re-set this force-flag here.
9085 */
9086 }
9087 else
9088 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9089
9090 /* We've injected the interrupt or taken necessary action, bail. */
9091 return VINF_SUCCESS;
9092 }
9093 else if (!fIsNestedGuest)
9094 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9095 }
9096 }
9097 else if (!fIsNestedGuest)
9098 {
9099 /*
9100 * An event is being injected or we are in an interrupt shadow. Check if another event is
9101 * pending. If so, instruct VT-x to cause a VM-exit as soon as the guest is ready to accept
9102 * the pending event.
9103 */
9104 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9105 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9106 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9107 && !pVCpu->hm.s.fSingleInstruction)
9108 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9109 }
9110 /* else: for nested-guests, NMI/interrupt-window exiting will be picked up when merging VMCS controls. */
9111
9112 return VINF_SUCCESS;
9113}
9114
9115
9116/**
9117 * Injects any pending events into the guest if the guest is in a state to
9118 * receive them.
9119 *
9120 * @returns Strict VBox status code (i.e. informational status codes too).
9121 * @param pVCpu The cross context virtual CPU structure.
9122 * @param pVmxTransient The VMX-transient structure.
9123 * @param fIntrState The VT-x guest-interruptibility state.
9124 * @param fStepping Whether we are single-stepping the guest using the
9125 * hypervisor debugger and should return
9126 * VINF_EM_DBG_STEPPED if the event was dispatched
9127 * directly.
9128 */
9129static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9130{
9131 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9132 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9133
9134#ifdef VBOX_STRICT
9135 /*
9136 * Verify guest-interruptibility state.
9137 *
9138 * We put this in a scoped block so we do not accidentally use fBlockSti or fBlockMovSS,
9139 * since injecting an event may modify the interruptibility state and we must thus always
9140 * use fIntrState.
9141 */
9142 {
9143 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9144 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9145 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9146 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9147 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9148 Assert(!TRPMHasTrap(pVCpu));
9149 NOREF(fBlockMovSS); NOREF(fBlockSti);
9150 }
9151#endif
9152
9153 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9154 if (pVCpu->hm.s.Event.fPending)
9155 {
9156 /*
9157 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9158 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9159 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9160 *
9161 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9162 */
9163 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9164#ifdef VBOX_STRICT
9165 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9166 {
9167 Assert(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9168 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9169 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9170 }
9171 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9172 {
9173 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI));
9174 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI));
9175 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9176 }
9177#endif
9178 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9179 uIntType));
9180
9181 /*
9182 * Inject the event and get any changes to the guest-interruptibility state.
9183 *
9184 * The guest-interruptibility state may need to be updated if we inject the event
9185 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9186 */
9187 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9188 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9189
9190 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9191 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9192 else
9193 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9194 }
9195
9196 /*
9197 * Deliver any pending debug exceptions if the guest is single-stepping using EFLAGS.TF and
9198 * is an interrupt shadow (block-by-STI or block-by-MOV SS).
9199 */
9200 if ( (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9201 && !pVmxTransient->fIsNestedGuest)
9202 {
9203 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9204
9205 if (!pVCpu->hm.s.fSingleInstruction)
9206 {
9207 /*
9208 * Set or clear the BS bit depending on whether the trap flag is active or not. We need
9209 * to do both since we clear the BS bit from the VMCS while exiting to ring-3.
9210 */
9211 Assert(!DBGFIsStepping(pVCpu));
9212 uint8_t const fTrapFlag = !!(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_TF);
9213 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, fTrapFlag << VMX_BF_VMCS_PENDING_DBG_XCPT_BS_SHIFT);
9214 AssertRC(rc);
9215 }
9216 else
9217 {
9218 /*
9219 * We must not deliver a debug exception when single-stepping over STI/Mov-SS in the
9220 * hypervisor debugger using EFLAGS.TF but rather clear interrupt inhibition. However,
9221 * we take care of this case in hmR0VmxExportSharedDebugState and also the case if
9222 * we use MTF, so just make sure it's called before executing guest-code.
9223 */
9224 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR_MASK);
9225 }
9226 }
9227 /* else: for nested-guest currently handling while merging controls. */
9228
9229 /*
9230 * Finally, update the guest-interruptibility state.
9231 *
9232 * This is required for the real-on-v86 software interrupt injection, for
9233 * pending debug exceptions as well as updates to the guest state from ring-3 (IEM).
9234 */
9235 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9236 AssertRC(rc);
9237
9238 /*
9239 * There's no need to clear the VM-entry interruption-information field here if we're not
9240 * injecting anything. VT-x clears the valid bit on every VM-exit.
9241 *
9242 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9243 */
9244
9245 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9246 return rcStrict;
9247}
9248
9249
9250/**
9251 * Enters the VT-x session.
9252 *
9253 * @returns VBox status code.
9254 * @param pVCpu The cross context virtual CPU structure.
9255 */
9256VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
9257{
9258 AssertPtr(pVCpu);
9259 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9260 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9261
9262 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9263 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9264 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9265
9266#ifdef VBOX_STRICT
9267 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9268 RTCCUINTREG uHostCr4 = ASMGetCR4();
9269 if (!(uHostCr4 & X86_CR4_VMXE))
9270 {
9271 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9272 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9273 }
9274#endif
9275
9276 /*
9277 * Load the appropriate VMCS as the current and active one.
9278 */
9279 PVMXVMCSINFO pVmcsInfo;
9280 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9281 if (!fInNestedGuestMode)
9282 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfo;
9283 else
9284 pVmcsInfo = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
9285 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9286 if (RT_SUCCESS(rc))
9287 {
9288 pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9289 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcsCopyForRing3 = fInNestedGuestMode;
9290 pVCpu->hmr0.s.fLeaveDone = false;
9291 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9292
9293 /*
9294 * Do the EMT scheduled L1D flush here if needed.
9295 */
9296 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9297 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9298 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9299 hmR0MdsClear();
9300 }
9301 return rc;
9302}
9303
9304
9305/**
9306 * The thread-context callback (only on platforms which support it).
9307 *
9308 * @param enmEvent The thread-context event.
9309 * @param pVCpu The cross context virtual CPU structure.
9310 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9311 * @thread EMT(pVCpu)
9312 */
9313VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
9314{
9315 AssertPtr(pVCpu);
9316 RT_NOREF1(fGlobalInit);
9317
9318 switch (enmEvent)
9319 {
9320 case RTTHREADCTXEVENT_OUT:
9321 {
9322 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9323 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9324 VMCPU_ASSERT_EMT(pVCpu);
9325
9326 /* No longjmps (logger flushes, locks) in this fragile context. */
9327 VMMRZCallRing3Disable(pVCpu);
9328 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9329
9330 /* Restore host-state (FPU, debug etc.) */
9331 if (!pVCpu->hmr0.s.fLeaveDone)
9332 {
9333 /*
9334 * Do -not- import the guest-state here as we might already be in the middle of importing
9335 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9336 */
9337 hmR0VmxLeave(pVCpu, false /* fImportState */);
9338 pVCpu->hmr0.s.fLeaveDone = true;
9339 }
9340
9341 /* Leave HM context, takes care of local init (term). */
9342 int rc = HMR0LeaveCpu(pVCpu);
9343 AssertRC(rc);
9344
9345 /* Restore longjmp state. */
9346 VMMRZCallRing3Enable(pVCpu);
9347 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9348 break;
9349 }
9350
9351 case RTTHREADCTXEVENT_IN:
9352 {
9353 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9354 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9355 VMCPU_ASSERT_EMT(pVCpu);
9356
9357 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9358 VMMRZCallRing3Disable(pVCpu);
9359 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9360
9361 /* Initialize the bare minimum state required for HM. This takes care of
9362 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9363 int rc = hmR0EnterCpu(pVCpu);
9364 AssertRC(rc);
9365 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9366 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9367
9368 /* Load the active VMCS as the current one. */
9369 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9370 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9371 AssertRC(rc);
9372 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9373 pVCpu->hmr0.s.fLeaveDone = false;
9374
9375 /* Do the EMT scheduled L1D flush if needed. */
9376 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9377 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9378
9379 /* Restore longjmp state. */
9380 VMMRZCallRing3Enable(pVCpu);
9381 break;
9382 }
9383
9384 default:
9385 break;
9386 }
9387}
9388
9389
9390/**
9391 * Exports the host state into the VMCS host-state area.
9392 * Sets up the VM-exit MSR-load area.
9393 *
9394 * The CPU state will be loaded from these fields on every successful VM-exit.
9395 *
9396 * @returns VBox status code.
9397 * @param pVCpu The cross context virtual CPU structure.
9398 *
9399 * @remarks No-long-jump zone!!!
9400 */
9401static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
9402{
9403 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9404
9405 int rc = VINF_SUCCESS;
9406 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9407 {
9408 uint64_t uHostCr4 = hmR0VmxExportHostControlRegs();
9409
9410 rc = hmR0VmxExportHostSegmentRegs(pVCpu, uHostCr4);
9411 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9412
9413 hmR0VmxExportHostMsrs(pVCpu);
9414
9415 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9416 }
9417 return rc;
9418}
9419
9420
9421/**
9422 * Saves the host state in the VMCS host-state.
9423 *
9424 * @returns VBox status code.
9425 * @param pVCpu The cross context virtual CPU structure.
9426 *
9427 * @remarks No-long-jump zone!!!
9428 */
9429VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
9430{
9431 AssertPtr(pVCpu);
9432 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9433
9434 /*
9435 * Export the host state here while entering HM context.
9436 * When thread-context hooks are used, we might get preempted and have to re-save the host
9437 * state but most of the time we won't be, so do it here before we disable interrupts.
9438 */
9439 return hmR0VmxExportHostState(pVCpu);
9440}
9441
9442
9443/**
9444 * Exports the guest state into the VMCS guest-state area.
9445 *
9446 * The will typically be done before VM-entry when the guest-CPU state and the
9447 * VMCS state may potentially be out of sync.
9448 *
9449 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9450 * VM-entry controls.
9451 * Sets up the appropriate VMX non-root function to execute guest code based on
9452 * the guest CPU mode.
9453 *
9454 * @returns VBox strict status code.
9455 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9456 * without unrestricted guest execution and the VMMDev is not presently
9457 * mapped (e.g. EFI32).
9458 *
9459 * @param pVCpu The cross context virtual CPU structure.
9460 * @param pVmxTransient The VMX-transient structure.
9461 *
9462 * @remarks No-long-jump zone!!!
9463 */
9464static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9465{
9466 AssertPtr(pVCpu);
9467 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9468 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9469
9470 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9471
9472 /*
9473 * Determine real-on-v86 mode.
9474 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9475 */
9476 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmxTransient->pVmcsInfo->pShared;
9477 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9478 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9479 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
9480 else
9481 {
9482 Assert(!pVmxTransient->fIsNestedGuest);
9483 pVmcsInfoShared->RealMode.fRealOnV86Active = true;
9484 }
9485
9486 /*
9487 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9488 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9489 */
9490 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9491 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9492
9493 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9494 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9495
9496 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9497 if (rcStrict == VINF_SUCCESS)
9498 { /* likely */ }
9499 else
9500 {
9501 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9502 return rcStrict;
9503 }
9504
9505 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9506 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9507
9508 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9509 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9510
9511 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9512 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9513 hmR0VmxExportGuestRip(pVCpu);
9514 hmR0VmxExportGuestRsp(pVCpu);
9515 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9516
9517 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9518 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9519
9520 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9521 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9522 | HM_CHANGED_GUEST_CR2
9523 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9524 | HM_CHANGED_GUEST_X87
9525 | HM_CHANGED_GUEST_SSE_AVX
9526 | HM_CHANGED_GUEST_OTHER_XSAVE
9527 | HM_CHANGED_GUEST_XCRx
9528 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9529 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9530 | HM_CHANGED_GUEST_TSC_AUX
9531 | HM_CHANGED_GUEST_OTHER_MSRS
9532 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9533
9534 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9535 return rc;
9536}
9537
9538
9539/**
9540 * Exports the state shared between the host and guest into the VMCS.
9541 *
9542 * @param pVCpu The cross context virtual CPU structure.
9543 * @param pVmxTransient The VMX-transient structure.
9544 *
9545 * @remarks No-long-jump zone!!!
9546 */
9547static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9548{
9549 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9550 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9551
9552 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9553 {
9554 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9555 AssertRC(rc);
9556 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9557
9558 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9559 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9560 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9561 }
9562
9563 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9564 {
9565 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9566 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9567 }
9568
9569 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9570 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9571}
9572
9573
9574/**
9575 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9576 *
9577 * @returns Strict VBox status code (i.e. informational status codes too).
9578 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9579 * without unrestricted guest execution and the VMMDev is not presently
9580 * mapped (e.g. EFI32).
9581 *
9582 * @param pVCpu The cross context virtual CPU structure.
9583 * @param pVmxTransient The VMX-transient structure.
9584 *
9585 * @remarks No-long-jump zone!!!
9586 */
9587static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9588{
9589 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9590 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9591 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9592
9593#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9594 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9595#endif
9596
9597 /*
9598 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9599 * changes. First try to export only these without going through all other changed-flag checks.
9600 */
9601 VBOXSTRICTRC rcStrict;
9602 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9603 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9604 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9605
9606 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9607 if ( (fCtxChanged & fMinimalMask)
9608 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9609 {
9610 hmR0VmxExportGuestRip(pVCpu);
9611 hmR0VmxExportGuestRsp(pVCpu);
9612 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9613 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9614 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9615 }
9616 /* If anything else also changed, go through the full export routine and export as required. */
9617 else if (fCtxChanged & fCtxMask)
9618 {
9619 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9620 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9621 { /* likely */}
9622 else
9623 {
9624 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9625 VBOXSTRICTRC_VAL(rcStrict)));
9626 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9627 return rcStrict;
9628 }
9629 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9630 }
9631 /* Nothing changed, nothing to load here. */
9632 else
9633 rcStrict = VINF_SUCCESS;
9634
9635#ifdef VBOX_STRICT
9636 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9637 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9638 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9639#endif
9640 return rcStrict;
9641}
9642
9643
9644/**
9645 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9646 * and update error record fields accordingly.
9647 *
9648 * @returns VMX_IGS_* error codes.
9649 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9650 * wrong with the guest state.
9651 *
9652 * @param pVCpu The cross context virtual CPU structure.
9653 * @param pVmcsInfo The VMCS info. object.
9654 *
9655 * @remarks This function assumes our cache of the VMCS controls
9656 * are valid, i.e. hmR0VmxCheckCachedVmcsCtls() succeeded.
9657 */
9658static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9659{
9660#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9661#define HMVMX_CHECK_BREAK(expr, err) do { \
9662 if (!(expr)) { uError = (err); break; } \
9663 } while (0)
9664
9665 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9666 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9667 uint32_t uError = VMX_IGS_ERROR;
9668 uint32_t u32IntrState = 0;
9669 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9670 do
9671 {
9672 int rc;
9673
9674 /*
9675 * Guest-interruptibility state.
9676 *
9677 * Read this first so that any check that fails prior to those that actually
9678 * require the guest-interruptibility state would still reflect the correct
9679 * VMCS value and avoids causing further confusion.
9680 */
9681 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9682 AssertRC(rc);
9683
9684 uint32_t u32Val;
9685 uint64_t u64Val;
9686
9687 /*
9688 * CR0.
9689 */
9690 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9691 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9692 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9693 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9694 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9695 if (fUnrestrictedGuest)
9696 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9697
9698 uint64_t u64GuestCr0;
9699 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9700 AssertRC(rc);
9701 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9702 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9703 if ( !fUnrestrictedGuest
9704 && (u64GuestCr0 & X86_CR0_PG)
9705 && !(u64GuestCr0 & X86_CR0_PE))
9706 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9707
9708 /*
9709 * CR4.
9710 */
9711 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9712 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9713 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9714
9715 uint64_t u64GuestCr4;
9716 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9717 AssertRC(rc);
9718 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9719 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9720
9721 /*
9722 * IA32_DEBUGCTL MSR.
9723 */
9724 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9725 AssertRC(rc);
9726 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9727 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9728 {
9729 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9730 }
9731 uint64_t u64DebugCtlMsr = u64Val;
9732
9733#ifdef VBOX_STRICT
9734 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9735 AssertRC(rc);
9736 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9737#endif
9738 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9739
9740 /*
9741 * RIP and RFLAGS.
9742 */
9743 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9744 AssertRC(rc);
9745 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9746 if ( !fLongModeGuest
9747 || !pCtx->cs.Attr.n.u1Long)
9748 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9749 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9750 * must be identical if the "IA-32e mode guest" VM-entry
9751 * control is 1 and CS.L is 1. No check applies if the
9752 * CPU supports 64 linear-address bits. */
9753
9754 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9755 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9756 AssertRC(rc);
9757 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9758 VMX_IGS_RFLAGS_RESERVED);
9759 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9760 uint32_t const u32Eflags = u64Val;
9761
9762 if ( fLongModeGuest
9763 || ( fUnrestrictedGuest
9764 && !(u64GuestCr0 & X86_CR0_PE)))
9765 {
9766 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9767 }
9768
9769 uint32_t u32EntryInfo;
9770 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9771 AssertRC(rc);
9772 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9773 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9774
9775 /*
9776 * 64-bit checks.
9777 */
9778 if (fLongModeGuest)
9779 {
9780 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9781 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9782 }
9783
9784 if ( !fLongModeGuest
9785 && (u64GuestCr4 & X86_CR4_PCIDE))
9786 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9787
9788 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9789 * 51:32 beyond the processor's physical-address width are 0. */
9790
9791 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9792 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9793 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9794
9795 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9796 AssertRC(rc);
9797 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9798
9799 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9800 AssertRC(rc);
9801 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9802
9803 /*
9804 * PERF_GLOBAL MSR.
9805 */
9806 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9807 {
9808 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9809 AssertRC(rc);
9810 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9811 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9812 }
9813
9814 /*
9815 * PAT MSR.
9816 */
9817 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9818 {
9819 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9820 AssertRC(rc);
9821 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9822 for (unsigned i = 0; i < 8; i++)
9823 {
9824 uint8_t u8Val = (u64Val & 0xff);
9825 if ( u8Val != 0 /* UC */
9826 && u8Val != 1 /* WC */
9827 && u8Val != 4 /* WT */
9828 && u8Val != 5 /* WP */
9829 && u8Val != 6 /* WB */
9830 && u8Val != 7 /* UC- */)
9831 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9832 u64Val >>= 8;
9833 }
9834 }
9835
9836 /*
9837 * EFER MSR.
9838 */
9839 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9840 {
9841 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9842 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9843 AssertRC(rc);
9844 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9845 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9846 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9847 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9848 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9849 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9850 * iemVmxVmentryCheckGuestState(). */
9851 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9852 || !(u64GuestCr0 & X86_CR0_PG)
9853 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9854 VMX_IGS_EFER_LMA_LME_MISMATCH);
9855 }
9856
9857 /*
9858 * Segment registers.
9859 */
9860 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9861 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9862 if (!(u32Eflags & X86_EFL_VM))
9863 {
9864 /* CS */
9865 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9866 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9867 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9868 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9869 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9870 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9871 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9872 /* CS cannot be loaded with NULL in protected mode. */
9873 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9874 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9875 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9876 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9877 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9878 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9879 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9880 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9881 else
9882 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9883
9884 /* SS */
9885 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9886 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9887 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9888 if ( !(pCtx->cr0 & X86_CR0_PE)
9889 || pCtx->cs.Attr.n.u4Type == 3)
9890 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9891
9892 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9893 {
9894 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9895 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9896 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9897 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9898 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9899 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9900 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9901 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9902 }
9903
9904 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9905 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9906 {
9907 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9908 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9909 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9910 || pCtx->ds.Attr.n.u4Type > 11
9911 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9912 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9913 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9914 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9915 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9916 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9917 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9918 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9919 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9920 }
9921 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9922 {
9923 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9924 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9925 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9926 || pCtx->es.Attr.n.u4Type > 11
9927 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9928 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9929 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9930 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9931 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9932 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9933 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9934 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9935 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9936 }
9937 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9938 {
9939 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9940 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9941 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9942 || pCtx->fs.Attr.n.u4Type > 11
9943 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9944 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9945 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9946 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9947 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9948 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9949 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9950 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9951 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9952 }
9953 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9954 {
9955 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9956 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9957 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9958 || pCtx->gs.Attr.n.u4Type > 11
9959 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9960 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9961 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9962 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9963 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9964 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9965 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9966 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9967 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9968 }
9969 /* 64-bit capable CPUs. */
9970 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9971 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9972 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9973 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9974 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9975 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9976 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9977 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9978 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9979 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9980 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9981 }
9982 else
9983 {
9984 /* V86 mode checks. */
9985 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9986 if (pVmcsInfo->pShared->RealMode.fRealOnV86Active)
9987 {
9988 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9989 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9990 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9991 }
9992 else
9993 {
9994 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9995 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9996 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9997 }
9998
9999 /* CS */
10000 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10001 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10002 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10003 /* SS */
10004 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10005 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10006 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10007 /* DS */
10008 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10009 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10010 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10011 /* ES */
10012 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10013 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10014 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10015 /* FS */
10016 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10017 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10018 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10019 /* GS */
10020 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10021 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10022 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10023 /* 64-bit capable CPUs. */
10024 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10025 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10026 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10027 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10028 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10029 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10030 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10031 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10032 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10033 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10034 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10035 }
10036
10037 /*
10038 * TR.
10039 */
10040 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10041 /* 64-bit capable CPUs. */
10042 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10043 if (fLongModeGuest)
10044 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10045 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10046 else
10047 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10048 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10049 VMX_IGS_TR_ATTR_TYPE_INVALID);
10050 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10051 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10052 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10053 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10054 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10055 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10056 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10057 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10058
10059 /*
10060 * GDTR and IDTR (64-bit capable checks).
10061 */
10062 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10063 AssertRC(rc);
10064 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10065
10066 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10067 AssertRC(rc);
10068 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10069
10070 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10071 AssertRC(rc);
10072 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10073
10074 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10075 AssertRC(rc);
10076 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10077
10078 /*
10079 * Guest Non-Register State.
10080 */
10081 /* Activity State. */
10082 uint32_t u32ActivityState;
10083 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10084 AssertRC(rc);
10085 HMVMX_CHECK_BREAK( !u32ActivityState
10086 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10087 VMX_IGS_ACTIVITY_STATE_INVALID);
10088 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10089 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10090
10091 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10092 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10093 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10094
10095 /** @todo Activity state and injecting interrupts. Left as a todo since we
10096 * currently don't use activity states but ACTIVE. */
10097
10098 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10099 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10100
10101 /* Guest interruptibility-state. */
10102 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10103 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10104 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10105 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10106 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10107 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10108 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10109 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10110 {
10111 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10112 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10113 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10114 }
10115 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10116 {
10117 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10118 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10119 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10120 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10121 }
10122 /** @todo Assumes the processor is not in SMM. */
10123 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10124 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10125 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10126 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10127 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10128 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10129 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10130 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10131
10132 /* Pending debug exceptions. */
10133 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10134 AssertRC(rc);
10135 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10136 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10137 u32Val = u64Val; /* For pending debug exceptions checks below. */
10138
10139 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10140 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10141 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10142 {
10143 if ( (u32Eflags & X86_EFL_TF)
10144 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10145 {
10146 /* Bit 14 is PendingDebug.BS. */
10147 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10148 }
10149 if ( !(u32Eflags & X86_EFL_TF)
10150 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10151 {
10152 /* Bit 14 is PendingDebug.BS. */
10153 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10154 }
10155 }
10156
10157 /* VMCS link pointer. */
10158 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10159 AssertRC(rc);
10160 if (u64Val != UINT64_C(0xffffffffffffffff))
10161 {
10162 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10163 /** @todo Bits beyond the processor's physical-address width MBZ. */
10164 /** @todo SMM checks. */
10165 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10166 Assert(pVmcsInfo->pvShadowVmcs);
10167 VMXVMCSREVID VmcsRevId;
10168 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10169 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10170 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10171 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10172 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10173 }
10174
10175 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10176 * not using nested paging? */
10177 if ( pVM->hm.s.fNestedPaging
10178 && !fLongModeGuest
10179 && CPUMIsGuestInPAEModeEx(pCtx))
10180 {
10181 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10182 AssertRC(rc);
10183 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10184
10185 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10186 AssertRC(rc);
10187 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10188
10189 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10190 AssertRC(rc);
10191 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10192
10193 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10194 AssertRC(rc);
10195 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10196 }
10197
10198 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10199 if (uError == VMX_IGS_ERROR)
10200 uError = VMX_IGS_REASON_NOT_FOUND;
10201 } while (0);
10202
10203 pVCpu->hm.s.u32HMError = uError;
10204 pVCpu->hm.s.vmx.LastError.u32GuestIntrState = u32IntrState;
10205 return uError;
10206
10207#undef HMVMX_ERROR_BREAK
10208#undef HMVMX_CHECK_BREAK
10209}
10210
10211
10212/**
10213 * Map the APIC-access page for virtualizing APIC accesses.
10214 *
10215 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10216 * this not done as part of exporting guest state, see @bugref{8721}.
10217 *
10218 * @returns VBox status code.
10219 * @param pVCpu The cross context virtual CPU structure.
10220 */
10221static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
10222{
10223 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10224 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10225
10226 Assert(PDMHasApic(pVM));
10227 Assert(u64MsrApicBase);
10228
10229 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10230 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10231
10232 /* Unalias the existing mapping. */
10233 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10234 AssertRCReturn(rc, rc);
10235
10236 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10237 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10238 rc = IOMR0MmioMapMmioHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10239 AssertRCReturn(rc, rc);
10240
10241 /* Update the per-VCPU cache of the APIC base MSR. */
10242 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10243 return VINF_SUCCESS;
10244}
10245
10246
10247/**
10248 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10249 * CPU.
10250 *
10251 * @param idCpu The ID for the CPU the function is called on.
10252 * @param pvUser1 Null, not used.
10253 * @param pvUser2 Null, not used.
10254 */
10255static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10256{
10257 RT_NOREF3(idCpu, pvUser1, pvUser2);
10258 VMXDispatchHostNmi();
10259}
10260
10261
10262/**
10263 * Dispatching an NMI on the host CPU that received it.
10264 *
10265 * @returns VBox status code.
10266 * @param pVCpu The cross context virtual CPU structure.
10267 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10268 * executing when receiving the host NMI in VMX non-root
10269 * operation.
10270 */
10271static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
10272{
10273 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
10274 Assert(idCpu != NIL_RTCPUID);
10275
10276 /*
10277 * We don't want to delay dispatching the NMI any more than we have to. However,
10278 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10279 * after executing guest or nested-guest code for the following reasons:
10280 *
10281 * - We would need to perform VMREADs with interrupts disabled and is orders of
10282 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
10283 * supported by the host hypervisor.
10284 *
10285 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10286 * longer period of time just for handling an edge case like host NMIs which do
10287 * not occur nearly as frequently as other VM-exits.
10288 *
10289 * Let's cover the most likely scenario first. Check if we are on the target CPU
10290 * and dispatch the NMI right away. This should be much faster than calling into
10291 * RTMpOnSpecific() machinery.
10292 */
10293 bool fDispatched = false;
10294 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10295 if (idCpu == RTMpCpuId())
10296 {
10297 VMXDispatchHostNmi();
10298 fDispatched = true;
10299 }
10300 ASMSetFlags(fEFlags);
10301 if (fDispatched)
10302 {
10303 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10304 return VINF_SUCCESS;
10305 }
10306
10307 /*
10308 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10309 * there should be no race or recursion even if we are unlucky enough to be preempted
10310 * (to the target CPU) without dispatching the host NMI above.
10311 */
10312 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10313 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10314}
10315
10316
10317#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10318/**
10319 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10320 * nested-guest using hardware-assisted VMX.
10321 *
10322 * @param pVCpu The cross context virtual CPU structure.
10323 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10324 * @param pVmcsInfoGst The guest VMCS info. object.
10325 */
10326static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10327{
10328 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10329 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10330 Assert(pu64MsrBitmap);
10331
10332 /*
10333 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10334 * MSR that is intercepted by the guest is also intercepted while executing the
10335 * nested-guest using hardware-assisted VMX.
10336 *
10337 * Note! If the nested-guest is not using an MSR bitmap, every MSR must cause a
10338 * nested-guest VM-exit even if the outer guest is not intercepting some
10339 * MSRs. We cannot assume the caller has initialized the nested-guest
10340 * MSR bitmap in this case.
10341 *
10342 * The nested hypervisor may also switch whether it uses MSR bitmaps for
10343 * each of its VM-entry, hence initializing it once per-VM while setting
10344 * up the nested-guest VMCS is not sufficient.
10345 */
10346 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10347 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10348 {
10349 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10350 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10351 Assert(pu64MsrBitmapNstGst);
10352 Assert(pu64MsrBitmapGst);
10353
10354 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10355 for (uint32_t i = 0; i < cFrags; i++)
10356 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10357 }
10358 else
10359 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10360}
10361
10362
10363/**
10364 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10365 * hardware-assisted VMX execution of the nested-guest.
10366 *
10367 * For a guest, we don't modify these controls once we set up the VMCS and hence
10368 * this function is never called.
10369 *
10370 * For nested-guests since the nested hypervisor provides these controls on every
10371 * nested-guest VM-entry and could potentially change them everytime we need to
10372 * merge them before every nested-guest VM-entry.
10373 *
10374 * @returns VBox status code.
10375 * @param pVCpu The cross context virtual CPU structure.
10376 */
10377static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
10378{
10379 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10380 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hmr0.s.vmx.VmcsInfo;
10381 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10382 Assert(pVmcsNstGst);
10383
10384 /*
10385 * Merge the controls with the requirements of the guest VMCS.
10386 *
10387 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10388 * VMCS with the features supported by the physical CPU as it's already done by the
10389 * VMLAUNCH/VMRESUME instruction emulation.
10390 *
10391 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10392 * derived from the VMX features supported by the physical CPU.
10393 */
10394
10395 /* Pin-based VM-execution controls. */
10396 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10397
10398 /* Processor-based VM-execution controls. */
10399 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10400 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10401 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10402 | VMX_PROC_CTLS_USE_TPR_SHADOW
10403 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10404
10405 /* Secondary processor-based VM-execution controls. */
10406 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10407 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10408 | VMX_PROC_CTLS2_INVPCID
10409 | VMX_PROC_CTLS2_VMCS_SHADOWING
10410 | VMX_PROC_CTLS2_RDTSCP
10411 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10412 | VMX_PROC_CTLS2_APIC_REG_VIRT
10413 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10414 | VMX_PROC_CTLS2_VMFUNC));
10415
10416 /*
10417 * VM-entry controls:
10418 * These controls contains state that depends on the nested-guest state (primarily
10419 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10420 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
10421 * properly continue executing the nested-guest if the EFER MSR changes but does not
10422 * cause a nested-guest VM-exits.
10423 *
10424 * VM-exit controls:
10425 * These controls specify the host state on return. We cannot use the controls from
10426 * the nested hypervisor state as is as it would contain the guest state rather than
10427 * the host state. Since the host state is subject to change (e.g. preemption, trips
10428 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10429 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10430 *
10431 * VM-entry MSR-load:
10432 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10433 * context by the VMLAUNCH/VMRESUME instruction emulation.
10434 *
10435 * VM-exit MSR-store:
10436 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10437 * back into the VM-exit MSR-store area.
10438 *
10439 * VM-exit MSR-load areas:
10440 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10441 * can entirely ignore what the nested hypervisor wants to load here.
10442 */
10443
10444 /*
10445 * Exception bitmap.
10446 *
10447 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10448 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10449 * code more flexible if intercepting exceptions become more dynamic in the future we do
10450 * it as part of exporting the nested-guest state.
10451 */
10452 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10453
10454 /*
10455 * CR0/CR4 guest/host mask.
10456 *
10457 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10458 * cause VM-exits, so we need to merge them here.
10459 */
10460 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10461 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10462
10463 /*
10464 * Page-fault error-code mask and match.
10465 *
10466 * Although we require unrestricted guest execution (and thereby nested-paging) for
10467 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10468 * normally intercept #PFs, it might intercept them for debugging purposes.
10469 *
10470 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10471 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10472 */
10473 uint32_t u32XcptPFMask;
10474 uint32_t u32XcptPFMatch;
10475 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10476 {
10477 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10478 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10479 }
10480 else
10481 {
10482 u32XcptPFMask = 0;
10483 u32XcptPFMatch = 0;
10484 }
10485
10486 /*
10487 * Pause-Loop exiting.
10488 */
10489 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10490 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10491
10492 /*
10493 * Pending debug exceptions.
10494 * Currently just copy whatever the nested-guest provides us.
10495 */
10496 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10497
10498 /*
10499 * I/O Bitmap.
10500 *
10501 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10502 * intercept all I/O port accesses.
10503 */
10504 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10505 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10506
10507 /*
10508 * VMCS shadowing.
10509 *
10510 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10511 * enabled while executing the nested-guest.
10512 */
10513 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10514
10515 /*
10516 * APIC-access page.
10517 */
10518 RTHCPHYS HCPhysApicAccess;
10519 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10520 {
10521 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10522 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10523
10524 /** @todo NSTVMX: This is not really correct but currently is required to make
10525 * things work. We need to re-enable the page handler when we fallback to
10526 * IEM execution of the nested-guest! */
10527 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10528
10529 void *pvPage;
10530 PGMPAGEMAPLOCK PgLockApicAccess;
10531 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10532 if (RT_SUCCESS(rc))
10533 {
10534 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10535 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10536
10537 /** @todo Handle proper releasing of page-mapping lock later. */
10538 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10539 }
10540 else
10541 return rc;
10542 }
10543 else
10544 HCPhysApicAccess = 0;
10545
10546 /*
10547 * Virtual-APIC page and TPR threshold.
10548 */
10549 RTHCPHYS HCPhysVirtApic;
10550 uint32_t u32TprThreshold;
10551 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10552 {
10553 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10554 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10555
10556 void *pvPage;
10557 PGMPAGEMAPLOCK PgLockVirtApic;
10558 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10559 if (RT_SUCCESS(rc))
10560 {
10561 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10562 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10563
10564 /** @todo Handle proper releasing of page-mapping lock later. */
10565 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10566 }
10567 else
10568 return rc;
10569
10570 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10571 }
10572 else
10573 {
10574 HCPhysVirtApic = 0;
10575 u32TprThreshold = 0;
10576
10577 /*
10578 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10579 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10580 * be taken care of by EPT/shadow paging.
10581 */
10582 if (pVM->hm.s.fAllow64BitGuests)
10583 {
10584 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10585 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10586 }
10587 }
10588
10589 /*
10590 * Validate basic assumptions.
10591 */
10592 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hmr0.s.vmx.VmcsInfoNstGst;
10593 Assert(pVM->hm.s.vmx.fUnrestrictedGuest);
10594 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10595 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10596
10597 /*
10598 * Commit it to the nested-guest VMCS.
10599 */
10600 int rc = VINF_SUCCESS;
10601 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10602 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10603 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10604 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10605 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10606 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10607 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10608 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10609 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10610 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10611 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10612 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10613 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10614 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10615 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10616 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10617 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10618 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10619 {
10620 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10621 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10622 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10623 }
10624 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10625 {
10626 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10627 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10628 }
10629 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10630 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10631 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10632 AssertRC(rc);
10633
10634 /*
10635 * Update the nested-guest VMCS cache.
10636 */
10637 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10638 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10639 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10640 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10641 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10642 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10643 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10644 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10645 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10646
10647 /*
10648 * We need to flush the TLB if we are switching the APIC-access page address.
10649 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10650 */
10651 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10652 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10653
10654 /*
10655 * MSR bitmap.
10656 *
10657 * The MSR bitmap address has already been initialized while setting up the nested-guest
10658 * VMCS, here we need to merge the MSR bitmaps.
10659 */
10660 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10661 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10662
10663 return VINF_SUCCESS;
10664}
10665#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10666
10667
10668/**
10669 * Does the preparations before executing guest code in VT-x.
10670 *
10671 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10672 * recompiler/IEM. We must be cautious what we do here regarding committing
10673 * guest-state information into the VMCS assuming we assuredly execute the
10674 * guest in VT-x mode.
10675 *
10676 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10677 * the common-state (TRPM/forceflags), we must undo those changes so that the
10678 * recompiler/IEM can (and should) use them when it resumes guest execution.
10679 * Otherwise such operations must be done when we can no longer exit to ring-3.
10680 *
10681 * @returns Strict VBox status code (i.e. informational status codes too).
10682 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10683 * have been disabled.
10684 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10685 * pending events).
10686 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10687 * double-fault into the guest.
10688 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10689 * dispatched directly.
10690 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10691 *
10692 * @param pVCpu The cross context virtual CPU structure.
10693 * @param pVmxTransient The VMX-transient structure.
10694 * @param fStepping Whether we are single-stepping the guest in the
10695 * hypervisor debugger. Makes us ignore some of the reasons
10696 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10697 * if event dispatching took place.
10698 */
10699static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10700{
10701 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10702
10703 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10704
10705#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10706 if (pVmxTransient->fIsNestedGuest)
10707 {
10708 RT_NOREF2(pVCpu, fStepping);
10709 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10710 return VINF_EM_RESCHEDULE_REM;
10711 }
10712#endif
10713
10714 /*
10715 * Check and process force flag actions, some of which might require us to go back to ring-3.
10716 */
10717 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, pVmxTransient, fStepping);
10718 if (rcStrict == VINF_SUCCESS)
10719 {
10720 /* FFs don't get set all the time. */
10721#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10722 if ( pVmxTransient->fIsNestedGuest
10723 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10724 {
10725 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10726 return VINF_VMX_VMEXIT;
10727 }
10728#endif
10729 }
10730 else
10731 return rcStrict;
10732
10733 /*
10734 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10735 */
10736 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10737 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10738 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10739 && PDMHasApic(pVM))
10740 {
10741 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10742 AssertRCReturn(rc, rc);
10743 }
10744
10745#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10746 /*
10747 * Merge guest VMCS controls with the nested-guest VMCS controls.
10748 *
10749 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10750 * saved state), we should be okay with merging controls as we initialize the
10751 * guest VMCS controls as part of VM setup phase.
10752 */
10753 if ( pVmxTransient->fIsNestedGuest
10754 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10755 {
10756 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10757 AssertRCReturn(rc, rc);
10758 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10759 }
10760#endif
10761
10762 /*
10763 * Evaluate events to be injected into the guest.
10764 *
10765 * Events in TRPM can be injected without inspecting the guest state.
10766 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10767 * guest to cause a VM-exit the next time they are ready to receive the event.
10768 *
10769 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10770 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10771 * subject to interecption. Otherwise, we should have checked and injected them
10772 * manually elsewhere (IEM).
10773 */
10774 if (TRPMHasTrap(pVCpu))
10775 {
10776 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10777 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10778 }
10779
10780 uint32_t fIntrState;
10781 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10782
10783#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10784 /*
10785 * While evaluating pending events if something failed (unlikely) or if we were
10786 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10787 */
10788 if (rcStrict != VINF_SUCCESS)
10789 return rcStrict;
10790 if ( pVmxTransient->fIsNestedGuest
10791 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10792 {
10793 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10794 return VINF_VMX_VMEXIT;
10795 }
10796#else
10797 Assert(rcStrict == VINF_SUCCESS);
10798#endif
10799
10800 /*
10801 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10802 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10803 * also result in triple-faulting the VM.
10804 *
10805 * With nested-guests, the above does not apply since unrestricted guest execution is a
10806 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10807 */
10808 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10809 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10810 { /* likely */ }
10811 else
10812 {
10813 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10814 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10815 return rcStrict;
10816 }
10817
10818 /*
10819 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10820 * import CR3 themselves. We will need to update them here, as even as late as the above
10821 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10822 * the below force flags to be set.
10823 */
10824 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10825 {
10826 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10827 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10828 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10829 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10830 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10831 }
10832 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10833 {
10834 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10835 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10836 }
10837
10838#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10839 /* Paranoia. */
10840 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10841#endif
10842
10843 /*
10844 * No longjmps to ring-3 from this point on!!!
10845 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10846 * This also disables flushing of the R0-logger instance (if any).
10847 */
10848 VMMRZCallRing3Disable(pVCpu);
10849
10850 /*
10851 * Export the guest state bits.
10852 *
10853 * We cannot perform longjmps while loading the guest state because we do not preserve the
10854 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10855 * CPU migration.
10856 *
10857 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10858 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10859 */
10860 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10861 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10862 { /* likely */ }
10863 else
10864 {
10865 VMMRZCallRing3Enable(pVCpu);
10866 return rcStrict;
10867 }
10868
10869 /*
10870 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10871 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10872 * preemption disabled for a while. Since this is purely to aid the
10873 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10874 * disable interrupt on NT.
10875 *
10876 * We need to check for force-flags that could've possible been altered since we last
10877 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10878 * see @bugref{6398}).
10879 *
10880 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10881 * to ring-3 before executing guest code.
10882 */
10883 pVmxTransient->fEFlags = ASMIntDisableFlags();
10884
10885 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10886 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10887 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10888 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10889 {
10890 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10891 {
10892#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10893 /*
10894 * If we are executing a nested-guest make sure that we should intercept subsequent
10895 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10896 * the VM-exit instruction emulation happy.
10897 */
10898 if (pVmxTransient->fIsNestedGuest)
10899 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10900#endif
10901
10902 /*
10903 * We've injected any pending events. This is really the point of no return (to ring-3).
10904 *
10905 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10906 * returns from this function, so do -not- enable them here.
10907 */
10908 pVCpu->hm.s.Event.fPending = false;
10909 return VINF_SUCCESS;
10910 }
10911
10912 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10913 rcStrict = VINF_EM_RAW_INTERRUPT;
10914 }
10915 else
10916 {
10917 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10918 rcStrict = VINF_EM_RAW_TO_R3;
10919 }
10920
10921 ASMSetFlags(pVmxTransient->fEFlags);
10922 VMMRZCallRing3Enable(pVCpu);
10923
10924 return rcStrict;
10925}
10926
10927
10928/**
10929 * Final preparations before executing guest code using hardware-assisted VMX.
10930 *
10931 * We can no longer get preempted to a different host CPU and there are no returns
10932 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10933 * failures), this function is not intended to fail sans unrecoverable hardware
10934 * errors.
10935 *
10936 * @param pVCpu The cross context virtual CPU structure.
10937 * @param pVmxTransient The VMX-transient structure.
10938 *
10939 * @remarks Called with preemption disabled.
10940 * @remarks No-long-jump zone!!!
10941 */
10942static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10943{
10944 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10945 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10946 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10947 Assert(!pVCpu->hm.s.Event.fPending);
10948
10949 /*
10950 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10951 */
10952 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10953 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10954
10955 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10956 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10957 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10958 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10959
10960 if (!CPUMIsGuestFPUStateActive(pVCpu))
10961 {
10962 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10963 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10964 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10965 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10966 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10967 }
10968
10969 /*
10970 * Re-export the host state bits as we may've been preempted (only happens when
10971 * thread-context hooks are used or when the VM start function changes) or if
10972 * the host CR0 is modified while loading the guest FPU state above.
10973 *
10974 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10975 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10976 * see @bugref{8432}.
10977 *
10978 * This may also happen when switching to/from a nested-guest VMCS without leaving
10979 * ring-0.
10980 */
10981 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10982 {
10983 hmR0VmxExportHostState(pVCpu);
10984 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10985 }
10986 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10987
10988 /*
10989 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10990 */
10991 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10992 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10993 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10994
10995 /*
10996 * Store status of the shared guest/host debug state at the time of VM-entry.
10997 */
10998 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10999 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11000
11001 /*
11002 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11003 * more than one conditional check. The post-run side of our code shall determine
11004 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11005 */
11006 if (pVmcsInfo->pbVirtApic)
11007 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11008
11009 /*
11010 * Update the host MSRs values in the VM-exit MSR-load area.
11011 */
11012 if (!pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs)
11013 {
11014 if (pVmcsInfo->cExitMsrLoad > 0)
11015 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11016 pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs = true;
11017 }
11018
11019 /*
11020 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11021 * VMX-preemption timer based on the next virtual sync clock deadline.
11022 */
11023 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11024 || idCurrentCpu != pVCpu->hmr0.s.idLastCpu)
11025 {
11026 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11027 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11028 }
11029
11030 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11031 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11032 if (!fIsRdtscIntercepted)
11033 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11034 else
11035 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11036
11037 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11038 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11039 Assert(idCurrentCpu == pVCpu->hmr0.s.idLastCpu);
11040 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
11041 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
11042 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
11043
11044 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11045
11046 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11047 as we're about to start executing the guest. */
11048
11049 /*
11050 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11051 *
11052 * This is done this late as updating the TSC offsetting/preemption timer above
11053 * figures out if we can skip intercepting RDTSCP by calculating the number of
11054 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11055 */
11056 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11057 && !fIsRdtscIntercepted)
11058 {
11059 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11060
11061 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11062 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11063 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11064 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11065 AssertRC(rc);
11066 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11067 pVmxTransient->fRemoveTscAuxMsr = true;
11068 }
11069
11070#ifdef VBOX_STRICT
11071 Assert(pVCpu->hmr0.s.vmx.fUpdatedHostAutoMsrs);
11072 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11073 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11074 AssertRC(hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11075#endif
11076
11077#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11078 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11079 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11080 * see @bugref{9180#c54}. */
11081 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11082 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11083 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11084#endif
11085}
11086
11087
11088/**
11089 * First C routine invoked after running guest code using hardware-assisted VMX.
11090 *
11091 * @param pVCpu The cross context virtual CPU structure.
11092 * @param pVmxTransient The VMX-transient structure.
11093 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11094 *
11095 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11096 *
11097 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11098 * unconditionally when it is safe to do so.
11099 */
11100static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11101{
11102 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11103
11104 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11105 ASMAtomicIncU32(&pVCpu->hmr0.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11106 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11107 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11108 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11109 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11110
11111 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11112 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11113 {
11114 uint64_t uGstTsc;
11115 if (!pVmxTransient->fIsNestedGuest)
11116 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11117 else
11118 {
11119 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11120 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11121 }
11122 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11123 }
11124
11125 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11126 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
11127 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11128
11129 pVCpu->hmr0.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11130 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11131#ifdef VBOX_STRICT
11132 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11133#endif
11134 Assert(!ASMIntAreEnabled());
11135 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11136 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11137
11138#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11139 /*
11140 * Clean all the VMCS fields in the transient structure before reading
11141 * anything from the VMCS.
11142 */
11143 pVmxTransient->uExitReason = 0;
11144 pVmxTransient->uExitIntErrorCode = 0;
11145 pVmxTransient->uExitQual = 0;
11146 pVmxTransient->uGuestLinearAddr = 0;
11147 pVmxTransient->uExitIntInfo = 0;
11148 pVmxTransient->cbExitInstr = 0;
11149 pVmxTransient->ExitInstrInfo.u = 0;
11150 pVmxTransient->uEntryIntInfo = 0;
11151 pVmxTransient->uEntryXcptErrorCode = 0;
11152 pVmxTransient->cbEntryInstr = 0;
11153 pVmxTransient->uIdtVectoringInfo = 0;
11154 pVmxTransient->uIdtVectoringErrorCode = 0;
11155#endif
11156
11157 /*
11158 * Save the basic VM-exit reason and check if the VM-entry failed.
11159 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11160 */
11161 uint32_t uExitReason;
11162 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11163 AssertRC(rc);
11164 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11165 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11166
11167 /*
11168 * Log the VM-exit before logging anything else as otherwise it might be a
11169 * tad confusing what happens before and after the world-switch.
11170 */
11171 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11172
11173 /*
11174 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11175 * bitmap permissions, if it was added before VM-entry.
11176 */
11177 if (pVmxTransient->fRemoveTscAuxMsr)
11178 {
11179 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11180 pVmxTransient->fRemoveTscAuxMsr = false;
11181 }
11182
11183 /*
11184 * Check if VMLAUNCH/VMRESUME succeeded.
11185 * If this failed, we cause a guru meditation and cease further execution.
11186 *
11187 * However, if we are executing a nested-guest we might fail if we use the
11188 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11189 */
11190 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11191 {
11192 /*
11193 * Update the VM-exit history array here even if the VM-entry failed due to:
11194 * - Invalid guest state.
11195 * - MSR loading.
11196 * - Machine-check event.
11197 *
11198 * In any of the above cases we will still have a "valid" VM-exit reason
11199 * despite @a fVMEntryFailed being false.
11200 *
11201 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11202 *
11203 * Note! We don't have CS or RIP at this point. Will probably address that later
11204 * by amending the history entry added here.
11205 */
11206 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11207 UINT64_MAX, uHostTsc);
11208
11209 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11210 {
11211 VMMRZCallRing3Enable(pVCpu);
11212
11213 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11214 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11215
11216#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11217 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
11218#endif
11219
11220 /*
11221 * Import the guest-interruptibility state always as we need it while evaluating
11222 * injecting events on re-entry.
11223 *
11224 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11225 * checking for real-mode while exporting the state because all bits that cause
11226 * mode changes wrt CR0 are intercepted.
11227 */
11228 uint64_t const fImportMask = CPUMCTX_EXTRN_HM_VMX_INT_STATE
11229#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11230 | HMVMX_CPUMCTX_EXTRN_ALL
11231#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11232 | CPUMCTX_EXTRN_RFLAGS
11233#endif
11234 ;
11235 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImportMask);
11236 AssertRC(rc);
11237
11238 /*
11239 * Sync the TPR shadow with our APIC state.
11240 */
11241 if ( !pVmxTransient->fIsNestedGuest
11242 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11243 {
11244 Assert(pVmcsInfo->pbVirtApic);
11245 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11246 {
11247 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11248 AssertRC(rc);
11249 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11250 }
11251 }
11252
11253 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11254 return;
11255 }
11256 }
11257#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11258 else if (pVmxTransient->fIsNestedGuest)
11259 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11260#endif
11261 else
11262 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11263
11264 VMMRZCallRing3Enable(pVCpu);
11265}
11266
11267
11268/**
11269 * Runs the guest code using hardware-assisted VMX the normal way.
11270 *
11271 * @returns VBox status code.
11272 * @param pVCpu The cross context virtual CPU structure.
11273 * @param pcLoops Pointer to the number of executed loops.
11274 */
11275static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
11276{
11277 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11278 Assert(pcLoops);
11279 Assert(*pcLoops <= cMaxResumeLoops);
11280 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11281
11282#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11283 /*
11284 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11285 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11286 * guest VMCS while entering the VMX ring-0 session.
11287 */
11288 if (pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11289 {
11290 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11291 if (RT_SUCCESS(rc))
11292 { /* likely */ }
11293 else
11294 {
11295 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11296 return rc;
11297 }
11298 }
11299#endif
11300
11301 VMXTRANSIENT VmxTransient;
11302 RT_ZERO(VmxTransient);
11303 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11304
11305 /* Paranoia. */
11306 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfo);
11307
11308 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11309 for (;;)
11310 {
11311 Assert(!HMR0SuspendPending());
11312 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11313 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11314
11315 /*
11316 * Preparatory work for running nested-guest code, this may force us to
11317 * return to ring-3.
11318 *
11319 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11320 */
11321 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11322 if (rcStrict != VINF_SUCCESS)
11323 break;
11324
11325 /* Interrupts are disabled at this point! */
11326 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11327 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11328 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11329 /* Interrupts are re-enabled at this point! */
11330
11331 /*
11332 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11333 */
11334 if (RT_SUCCESS(rcRun))
11335 { /* very likely */ }
11336 else
11337 {
11338 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11339 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11340 return rcRun;
11341 }
11342
11343 /*
11344 * Profile the VM-exit.
11345 */
11346 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11347 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11348 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11349 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11350 HMVMX_START_EXIT_DISPATCH_PROF();
11351
11352 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11353
11354 /*
11355 * Handle the VM-exit.
11356 */
11357#ifdef HMVMX_USE_FUNCTION_TABLE
11358 rcStrict = g_aVMExitHandlers[VmxTransient.uExitReason].pfn(pVCpu, &VmxTransient);
11359#else
11360 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11361#endif
11362 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11363 if (rcStrict == VINF_SUCCESS)
11364 {
11365 if (++(*pcLoops) <= cMaxResumeLoops)
11366 continue;
11367 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11368 rcStrict = VINF_EM_RAW_INTERRUPT;
11369 }
11370 break;
11371 }
11372
11373 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11374 return rcStrict;
11375}
11376
11377
11378#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11379/**
11380 * Runs the nested-guest code using hardware-assisted VMX.
11381 *
11382 * @returns VBox status code.
11383 * @param pVCpu The cross context virtual CPU structure.
11384 * @param pcLoops Pointer to the number of executed loops.
11385 *
11386 * @sa hmR0VmxRunGuestCodeNormal.
11387 */
11388static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
11389{
11390 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11391 Assert(pcLoops);
11392 Assert(*pcLoops <= cMaxResumeLoops);
11393 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11394
11395 /*
11396 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11397 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11398 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11399 */
11400 if (!pVCpu->hmr0.s.vmx.fSwitchedToNstGstVmcs)
11401 {
11402 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11403 if (RT_SUCCESS(rc))
11404 { /* likely */ }
11405 else
11406 {
11407 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11408 return rc;
11409 }
11410 }
11411
11412 VMXTRANSIENT VmxTransient;
11413 RT_ZERO(VmxTransient);
11414 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11415 VmxTransient.fIsNestedGuest = true;
11416
11417 /* Paranoia. */
11418 Assert(VmxTransient.pVmcsInfo == &pVCpu->hmr0.s.vmx.VmcsInfoNstGst);
11419
11420 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11421 for (;;)
11422 {
11423 Assert(!HMR0SuspendPending());
11424 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11425 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11426
11427 /*
11428 * Preparatory work for running guest code, this may force us to
11429 * return to ring-3.
11430 *
11431 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11432 */
11433 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11434 if (rcStrict != VINF_SUCCESS)
11435 break;
11436
11437 /* Interrupts are disabled at this point! */
11438 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11439 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11440 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11441 /* Interrupts are re-enabled at this point! */
11442
11443 /*
11444 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11445 */
11446 if (RT_SUCCESS(rcRun))
11447 { /* very likely */ }
11448 else
11449 {
11450 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11451 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11452 return rcRun;
11453 }
11454
11455 /*
11456 * Profile the VM-exit.
11457 */
11458 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11459 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11460 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11461 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11462 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11463 HMVMX_START_EXIT_DISPATCH_PROF();
11464
11465 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11466
11467 /*
11468 * Handle the VM-exit.
11469 */
11470 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11471 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11472 if (rcStrict == VINF_SUCCESS)
11473 {
11474 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11475 {
11476 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11477 rcStrict = VINF_VMX_VMEXIT;
11478 }
11479 else
11480 {
11481 if (++(*pcLoops) <= cMaxResumeLoops)
11482 continue;
11483 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11484 rcStrict = VINF_EM_RAW_INTERRUPT;
11485 }
11486 }
11487 else
11488 Assert(rcStrict != VINF_VMX_VMEXIT);
11489 break;
11490 }
11491
11492 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11493 return rcStrict;
11494}
11495#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11496
11497
11498/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11499 * probes.
11500 *
11501 * The following few functions and associated structure contains the bloat
11502 * necessary for providing detailed debug events and dtrace probes as well as
11503 * reliable host side single stepping. This works on the principle of
11504 * "subclassing" the normal execution loop and workers. We replace the loop
11505 * method completely and override selected helpers to add necessary adjustments
11506 * to their core operation.
11507 *
11508 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11509 * any performance for debug and analysis features.
11510 *
11511 * @{
11512 */
11513
11514/**
11515 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11516 * the debug run loop.
11517 */
11518typedef struct VMXRUNDBGSTATE
11519{
11520 /** The RIP we started executing at. This is for detecting that we stepped. */
11521 uint64_t uRipStart;
11522 /** The CS we started executing with. */
11523 uint16_t uCsStart;
11524
11525 /** Whether we've actually modified the 1st execution control field. */
11526 bool fModifiedProcCtls : 1;
11527 /** Whether we've actually modified the 2nd execution control field. */
11528 bool fModifiedProcCtls2 : 1;
11529 /** Whether we've actually modified the exception bitmap. */
11530 bool fModifiedXcptBitmap : 1;
11531
11532 /** We desire the modified the CR0 mask to be cleared. */
11533 bool fClearCr0Mask : 1;
11534 /** We desire the modified the CR4 mask to be cleared. */
11535 bool fClearCr4Mask : 1;
11536 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11537 uint32_t fCpe1Extra;
11538 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11539 uint32_t fCpe1Unwanted;
11540 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11541 uint32_t fCpe2Extra;
11542 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11543 uint32_t bmXcptExtra;
11544 /** The sequence number of the Dtrace provider settings the state was
11545 * configured against. */
11546 uint32_t uDtraceSettingsSeqNo;
11547 /** VM-exits to check (one bit per VM-exit). */
11548 uint32_t bmExitsToCheck[3];
11549
11550 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11551 uint32_t fProcCtlsInitial;
11552 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11553 uint32_t fProcCtls2Initial;
11554 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11555 uint32_t bmXcptInitial;
11556} VMXRUNDBGSTATE;
11557AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11558typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11559
11560
11561/**
11562 * Initializes the VMXRUNDBGSTATE structure.
11563 *
11564 * @param pVCpu The cross context virtual CPU structure of the
11565 * calling EMT.
11566 * @param pVmxTransient The VMX-transient structure.
11567 * @param pDbgState The debug state to initialize.
11568 */
11569static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11570{
11571 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11572 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11573
11574 pDbgState->fModifiedProcCtls = false;
11575 pDbgState->fModifiedProcCtls2 = false;
11576 pDbgState->fModifiedXcptBitmap = false;
11577 pDbgState->fClearCr0Mask = false;
11578 pDbgState->fClearCr4Mask = false;
11579 pDbgState->fCpe1Extra = 0;
11580 pDbgState->fCpe1Unwanted = 0;
11581 pDbgState->fCpe2Extra = 0;
11582 pDbgState->bmXcptExtra = 0;
11583 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11584 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11585 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11586}
11587
11588
11589/**
11590 * Updates the VMSC fields with changes requested by @a pDbgState.
11591 *
11592 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11593 * immediately before executing guest code, i.e. when interrupts are disabled.
11594 * We don't check status codes here as we cannot easily assert or return in the
11595 * latter case.
11596 *
11597 * @param pVCpu The cross context virtual CPU structure.
11598 * @param pVmxTransient The VMX-transient structure.
11599 * @param pDbgState The debug state.
11600 */
11601static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11602{
11603 /*
11604 * Ensure desired flags in VMCS control fields are set.
11605 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11606 *
11607 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11608 * there should be no stale data in pCtx at this point.
11609 */
11610 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11611 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11612 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11613 {
11614 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11615 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11616 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11617 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11618 pDbgState->fModifiedProcCtls = true;
11619 }
11620
11621 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11622 {
11623 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11624 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11625 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11626 pDbgState->fModifiedProcCtls2 = true;
11627 }
11628
11629 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11630 {
11631 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11632 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11633 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11634 pDbgState->fModifiedXcptBitmap = true;
11635 }
11636
11637 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11638 {
11639 pVmcsInfo->u64Cr0Mask = 0;
11640 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11641 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11642 }
11643
11644 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11645 {
11646 pVmcsInfo->u64Cr4Mask = 0;
11647 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11648 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11649 }
11650
11651 NOREF(pVCpu);
11652}
11653
11654
11655/**
11656 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11657 * re-entry next time around.
11658 *
11659 * @returns Strict VBox status code (i.e. informational status codes too).
11660 * @param pVCpu The cross context virtual CPU structure.
11661 * @param pVmxTransient The VMX-transient structure.
11662 * @param pDbgState The debug state.
11663 * @param rcStrict The return code from executing the guest using single
11664 * stepping.
11665 */
11666static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11667 VBOXSTRICTRC rcStrict)
11668{
11669 /*
11670 * Restore VM-exit control settings as we may not reenter this function the
11671 * next time around.
11672 */
11673 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11674
11675 /* We reload the initial value, trigger what we can of recalculations the
11676 next time around. From the looks of things, that's all that's required atm. */
11677 if (pDbgState->fModifiedProcCtls)
11678 {
11679 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11680 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11681 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11682 AssertRC(rc2);
11683 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11684 }
11685
11686 /* We're currently the only ones messing with this one, so just restore the
11687 cached value and reload the field. */
11688 if ( pDbgState->fModifiedProcCtls2
11689 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11690 {
11691 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11692 AssertRC(rc2);
11693 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11694 }
11695
11696 /* If we've modified the exception bitmap, we restore it and trigger
11697 reloading and partial recalculation the next time around. */
11698 if (pDbgState->fModifiedXcptBitmap)
11699 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11700
11701 return rcStrict;
11702}
11703
11704
11705/**
11706 * Configures VM-exit controls for current DBGF and DTrace settings.
11707 *
11708 * This updates @a pDbgState and the VMCS execution control fields to reflect
11709 * the necessary VM-exits demanded by DBGF and DTrace.
11710 *
11711 * @param pVCpu The cross context virtual CPU structure.
11712 * @param pVmxTransient The VMX-transient structure. May update
11713 * fUpdatedTscOffsettingAndPreemptTimer.
11714 * @param pDbgState The debug state.
11715 */
11716static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11717{
11718 /*
11719 * Take down the dtrace serial number so we can spot changes.
11720 */
11721 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11722 ASMCompilerBarrier();
11723
11724 /*
11725 * We'll rebuild most of the middle block of data members (holding the
11726 * current settings) as we go along here, so start by clearing it all.
11727 */
11728 pDbgState->bmXcptExtra = 0;
11729 pDbgState->fCpe1Extra = 0;
11730 pDbgState->fCpe1Unwanted = 0;
11731 pDbgState->fCpe2Extra = 0;
11732 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11733 pDbgState->bmExitsToCheck[i] = 0;
11734
11735 /*
11736 * Software interrupts (INT XXh) - no idea how to trigger these...
11737 */
11738 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11739 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11740 || VBOXVMM_INT_SOFTWARE_ENABLED())
11741 {
11742 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11743 }
11744
11745 /*
11746 * INT3 breakpoints - triggered by #BP exceptions.
11747 */
11748 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11749 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11750
11751 /*
11752 * Exception bitmap and XCPT events+probes.
11753 */
11754 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11755 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11756 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11757
11758 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11759 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11760 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11761 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11762 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11763 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11764 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11765 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11766 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11767 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11768 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11769 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11770 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11771 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11772 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11773 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11774 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11775 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11776
11777 if (pDbgState->bmXcptExtra)
11778 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11779
11780 /*
11781 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11782 *
11783 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11784 * So, when adding/changing/removing please don't forget to update it.
11785 *
11786 * Some of the macros are picking up local variables to save horizontal space,
11787 * (being able to see it in a table is the lesser evil here).
11788 */
11789#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11790 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11791 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11792#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11793 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11794 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11795 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11796 } else do { } while (0)
11797#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11798 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11799 { \
11800 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11801 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11802 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11803 } else do { } while (0)
11804#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11805 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11806 { \
11807 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11808 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11809 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11810 } else do { } while (0)
11811#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11812 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11813 { \
11814 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11815 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11816 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11817 } else do { } while (0)
11818
11819 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11820 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11821 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11822 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11823 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11824
11825 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11826 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11827 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11828 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11829 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11830 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11831 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11832 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11833 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11834 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11835 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11836 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11837 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11838 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11839 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11840 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11841 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11842 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11843 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11844 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11845 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11846 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11847 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11848 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11849 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11850 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11851 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11852 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11853 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11854 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11855 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11856 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11857 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11858 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11859 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11860 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11861
11862 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11863 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11864 {
11865 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11866 | CPUMCTX_EXTRN_APIC_TPR);
11867 AssertRC(rc);
11868
11869#if 0 /** @todo fix me */
11870 pDbgState->fClearCr0Mask = true;
11871 pDbgState->fClearCr4Mask = true;
11872#endif
11873 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11874 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11875 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11876 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11877 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11878 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11879 require clearing here and in the loop if we start using it. */
11880 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11881 }
11882 else
11883 {
11884 if (pDbgState->fClearCr0Mask)
11885 {
11886 pDbgState->fClearCr0Mask = false;
11887 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11888 }
11889 if (pDbgState->fClearCr4Mask)
11890 {
11891 pDbgState->fClearCr4Mask = false;
11892 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11893 }
11894 }
11895 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11896 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11897
11898 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11899 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11900 {
11901 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11902 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11903 }
11904 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11905 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11906
11907 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11908 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11909 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11910 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11911 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11912 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11913 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11914 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11915#if 0 /** @todo too slow, fix handler. */
11916 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11917#endif
11918 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11919
11920 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11921 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11922 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11923 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11924 {
11925 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11926 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11927 }
11928 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11929 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11930 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11931 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11932
11933 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11934 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11935 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11936 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11937 {
11938 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11939 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11940 }
11941 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11942 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11943 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11944 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11945
11946 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11947 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11948 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11949 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11950 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11951 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11952 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11953 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11954 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11955 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11956 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11957 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11958 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11959 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11960 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11961 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11962 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11963 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11964 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11965 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11966 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11967 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11968
11969#undef IS_EITHER_ENABLED
11970#undef SET_ONLY_XBM_IF_EITHER_EN
11971#undef SET_CPE1_XBM_IF_EITHER_EN
11972#undef SET_CPEU_XBM_IF_EITHER_EN
11973#undef SET_CPE2_XBM_IF_EITHER_EN
11974
11975 /*
11976 * Sanitize the control stuff.
11977 */
11978 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11979 if (pDbgState->fCpe2Extra)
11980 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11981 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11982 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11983 if (pVCpu->hmr0.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11984 {
11985 pVCpu->hmr0.s.fDebugWantRdTscExit ^= true;
11986 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11987 }
11988
11989 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11990 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11991 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11992 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11993}
11994
11995
11996/**
11997 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11998 * appropriate.
11999 *
12000 * The caller has checked the VM-exit against the
12001 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12002 * already, so we don't have to do that either.
12003 *
12004 * @returns Strict VBox status code (i.e. informational status codes too).
12005 * @param pVCpu The cross context virtual CPU structure.
12006 * @param pVmxTransient The VMX-transient structure.
12007 * @param uExitReason The VM-exit reason.
12008 *
12009 * @remarks The name of this function is displayed by dtrace, so keep it short
12010 * and to the point. No longer than 33 chars long, please.
12011 */
12012static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12013{
12014 /*
12015 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12016 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12017 *
12018 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12019 * does. Must add/change/remove both places. Same ordering, please.
12020 *
12021 * Added/removed events must also be reflected in the next section
12022 * where we dispatch dtrace events.
12023 */
12024 bool fDtrace1 = false;
12025 bool fDtrace2 = false;
12026 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12027 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12028 uint32_t uEventArg = 0;
12029#define SET_EXIT(a_EventSubName) \
12030 do { \
12031 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12032 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12033 } while (0)
12034#define SET_BOTH(a_EventSubName) \
12035 do { \
12036 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12037 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12038 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12039 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12040 } while (0)
12041 switch (uExitReason)
12042 {
12043 case VMX_EXIT_MTF:
12044 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12045
12046 case VMX_EXIT_XCPT_OR_NMI:
12047 {
12048 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12049 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12050 {
12051 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12052 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12053 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12054 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12055 {
12056 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12057 {
12058 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12059 uEventArg = pVmxTransient->uExitIntErrorCode;
12060 }
12061 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12062 switch (enmEvent1)
12063 {
12064 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12065 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12066 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12067 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12068 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12069 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12070 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12071 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12072 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12073 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12074 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12075 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12076 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12077 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12078 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12079 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12080 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12081 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12082 default: break;
12083 }
12084 }
12085 else
12086 AssertFailed();
12087 break;
12088
12089 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12090 uEventArg = idxVector;
12091 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12092 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12093 break;
12094 }
12095 break;
12096 }
12097
12098 case VMX_EXIT_TRIPLE_FAULT:
12099 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12100 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12101 break;
12102 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12103 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12104 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12105 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12106 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12107
12108 /* Instruction specific VM-exits: */
12109 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12110 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12111 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12112 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12113 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12114 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12115 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12116 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12117 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12118 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12119 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12120 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12121 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12122 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12123 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12124 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12125 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12126 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12127 case VMX_EXIT_MOV_CRX:
12128 hmR0VmxReadExitQualVmcs(pVmxTransient);
12129 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12130 SET_BOTH(CRX_READ);
12131 else
12132 SET_BOTH(CRX_WRITE);
12133 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12134 break;
12135 case VMX_EXIT_MOV_DRX:
12136 hmR0VmxReadExitQualVmcs(pVmxTransient);
12137 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12138 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12139 SET_BOTH(DRX_READ);
12140 else
12141 SET_BOTH(DRX_WRITE);
12142 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12143 break;
12144 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12145 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12146 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12147 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12148 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12149 case VMX_EXIT_GDTR_IDTR_ACCESS:
12150 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12151 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12152 {
12153 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12154 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12155 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12156 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12157 }
12158 break;
12159
12160 case VMX_EXIT_LDTR_TR_ACCESS:
12161 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12162 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12163 {
12164 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12165 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12166 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12167 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12168 }
12169 break;
12170
12171 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12172 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12173 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12174 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12175 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12176 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12177 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12178 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12179 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12180 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12181 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12182
12183 /* Events that aren't relevant at this point. */
12184 case VMX_EXIT_EXT_INT:
12185 case VMX_EXIT_INT_WINDOW:
12186 case VMX_EXIT_NMI_WINDOW:
12187 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12188 case VMX_EXIT_PREEMPT_TIMER:
12189 case VMX_EXIT_IO_INSTR:
12190 break;
12191
12192 /* Errors and unexpected events. */
12193 case VMX_EXIT_INIT_SIGNAL:
12194 case VMX_EXIT_SIPI:
12195 case VMX_EXIT_IO_SMI:
12196 case VMX_EXIT_SMI:
12197 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12198 case VMX_EXIT_ERR_MSR_LOAD:
12199 case VMX_EXIT_ERR_MACHINE_CHECK:
12200 case VMX_EXIT_PML_FULL:
12201 case VMX_EXIT_VIRTUALIZED_EOI:
12202 break;
12203
12204 default:
12205 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12206 break;
12207 }
12208#undef SET_BOTH
12209#undef SET_EXIT
12210
12211 /*
12212 * Dtrace tracepoints go first. We do them here at once so we don't
12213 * have to copy the guest state saving and stuff a few dozen times.
12214 * Down side is that we've got to repeat the switch, though this time
12215 * we use enmEvent since the probes are a subset of what DBGF does.
12216 */
12217 if (fDtrace1 || fDtrace2)
12218 {
12219 hmR0VmxReadExitQualVmcs(pVmxTransient);
12220 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12221 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12222 switch (enmEvent1)
12223 {
12224 /** @todo consider which extra parameters would be helpful for each probe. */
12225 case DBGFEVENT_END: break;
12226 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12227 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12228 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12229 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12230 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12231 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12232 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12233 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12234 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12235 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12236 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12237 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12238 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12239 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12240 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12241 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12242 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12243 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12244 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12245 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12246 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12247 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12248 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12249 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12250 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12251 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12252 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12253 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12254 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12255 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12256 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12257 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12258 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12259 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12260 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12261 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12262 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12263 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12264 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12265 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12266 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12267 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12268 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12269 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12270 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12271 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12272 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12273 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12274 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12275 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12276 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12277 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12278 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12279 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12280 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12281 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12282 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12283 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12284 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12285 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12286 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12287 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12288 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12289 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12290 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12291 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12292 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12293 }
12294 switch (enmEvent2)
12295 {
12296 /** @todo consider which extra parameters would be helpful for each probe. */
12297 case DBGFEVENT_END: break;
12298 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12299 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12300 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12301 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12302 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12303 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12304 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12305 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12306 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12307 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12308 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12309 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12310 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12311 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12312 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12313 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12314 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12315 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12316 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12317 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12318 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12319 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12320 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12321 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12322 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12323 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12324 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12325 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12326 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12327 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12328 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12329 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12330 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12331 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12332 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12333 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12334 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12335 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12336 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12337 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12338 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12339 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12340 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12341 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12342 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12343 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12344 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12345 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12346 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12347 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12348 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12349 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12350 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12351 }
12352 }
12353
12354 /*
12355 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12356 * the DBGF call will do a full check).
12357 *
12358 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12359 * Note! If we have to events, we prioritize the first, i.e. the instruction
12360 * one, in order to avoid event nesting.
12361 */
12362 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
12363 if ( enmEvent1 != DBGFEVENT_END
12364 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12365 {
12366 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12367 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12368 if (rcStrict != VINF_SUCCESS)
12369 return rcStrict;
12370 }
12371 else if ( enmEvent2 != DBGFEVENT_END
12372 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12373 {
12374 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12375 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12376 if (rcStrict != VINF_SUCCESS)
12377 return rcStrict;
12378 }
12379
12380 return VINF_SUCCESS;
12381}
12382
12383
12384/**
12385 * Single-stepping VM-exit filtering.
12386 *
12387 * This is preprocessing the VM-exits and deciding whether we've gotten far
12388 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12389 * handling is performed.
12390 *
12391 * @returns Strict VBox status code (i.e. informational status codes too).
12392 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12393 * @param pVmxTransient The VMX-transient structure.
12394 * @param pDbgState The debug state.
12395 */
12396DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12397{
12398 /*
12399 * Expensive (saves context) generic dtrace VM-exit probe.
12400 */
12401 uint32_t const uExitReason = pVmxTransient->uExitReason;
12402 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12403 { /* more likely */ }
12404 else
12405 {
12406 hmR0VmxReadExitQualVmcs(pVmxTransient);
12407 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12408 AssertRC(rc);
12409 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12410 }
12411
12412 /*
12413 * Check for host NMI, just to get that out of the way.
12414 */
12415 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12416 { /* normally likely */ }
12417 else
12418 {
12419 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12420 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12421 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12422 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12423 }
12424
12425 /*
12426 * Check for single stepping event if we're stepping.
12427 */
12428 if (pVCpu->hm.s.fSingleInstruction)
12429 {
12430 switch (uExitReason)
12431 {
12432 case VMX_EXIT_MTF:
12433 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12434
12435 /* Various events: */
12436 case VMX_EXIT_XCPT_OR_NMI:
12437 case VMX_EXIT_EXT_INT:
12438 case VMX_EXIT_TRIPLE_FAULT:
12439 case VMX_EXIT_INT_WINDOW:
12440 case VMX_EXIT_NMI_WINDOW:
12441 case VMX_EXIT_TASK_SWITCH:
12442 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12443 case VMX_EXIT_APIC_ACCESS:
12444 case VMX_EXIT_EPT_VIOLATION:
12445 case VMX_EXIT_EPT_MISCONFIG:
12446 case VMX_EXIT_PREEMPT_TIMER:
12447
12448 /* Instruction specific VM-exits: */
12449 case VMX_EXIT_CPUID:
12450 case VMX_EXIT_GETSEC:
12451 case VMX_EXIT_HLT:
12452 case VMX_EXIT_INVD:
12453 case VMX_EXIT_INVLPG:
12454 case VMX_EXIT_RDPMC:
12455 case VMX_EXIT_RDTSC:
12456 case VMX_EXIT_RSM:
12457 case VMX_EXIT_VMCALL:
12458 case VMX_EXIT_VMCLEAR:
12459 case VMX_EXIT_VMLAUNCH:
12460 case VMX_EXIT_VMPTRLD:
12461 case VMX_EXIT_VMPTRST:
12462 case VMX_EXIT_VMREAD:
12463 case VMX_EXIT_VMRESUME:
12464 case VMX_EXIT_VMWRITE:
12465 case VMX_EXIT_VMXOFF:
12466 case VMX_EXIT_VMXON:
12467 case VMX_EXIT_MOV_CRX:
12468 case VMX_EXIT_MOV_DRX:
12469 case VMX_EXIT_IO_INSTR:
12470 case VMX_EXIT_RDMSR:
12471 case VMX_EXIT_WRMSR:
12472 case VMX_EXIT_MWAIT:
12473 case VMX_EXIT_MONITOR:
12474 case VMX_EXIT_PAUSE:
12475 case VMX_EXIT_GDTR_IDTR_ACCESS:
12476 case VMX_EXIT_LDTR_TR_ACCESS:
12477 case VMX_EXIT_INVEPT:
12478 case VMX_EXIT_RDTSCP:
12479 case VMX_EXIT_INVVPID:
12480 case VMX_EXIT_WBINVD:
12481 case VMX_EXIT_XSETBV:
12482 case VMX_EXIT_RDRAND:
12483 case VMX_EXIT_INVPCID:
12484 case VMX_EXIT_VMFUNC:
12485 case VMX_EXIT_RDSEED:
12486 case VMX_EXIT_XSAVES:
12487 case VMX_EXIT_XRSTORS:
12488 {
12489 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12490 AssertRCReturn(rc, rc);
12491 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12492 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12493 return VINF_EM_DBG_STEPPED;
12494 break;
12495 }
12496
12497 /* Errors and unexpected events: */
12498 case VMX_EXIT_INIT_SIGNAL:
12499 case VMX_EXIT_SIPI:
12500 case VMX_EXIT_IO_SMI:
12501 case VMX_EXIT_SMI:
12502 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12503 case VMX_EXIT_ERR_MSR_LOAD:
12504 case VMX_EXIT_ERR_MACHINE_CHECK:
12505 case VMX_EXIT_PML_FULL:
12506 case VMX_EXIT_VIRTUALIZED_EOI:
12507 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12508 break;
12509
12510 default:
12511 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12512 break;
12513 }
12514 }
12515
12516 /*
12517 * Check for debugger event breakpoints and dtrace probes.
12518 */
12519 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12520 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12521 {
12522 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12523 if (rcStrict != VINF_SUCCESS)
12524 return rcStrict;
12525 }
12526
12527 /*
12528 * Normal processing.
12529 */
12530#ifdef HMVMX_USE_FUNCTION_TABLE
12531 return g_aVMExitHandlers[uExitReason].pfn(pVCpu, pVmxTransient);
12532#else
12533 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12534#endif
12535}
12536
12537
12538/**
12539 * Single steps guest code using hardware-assisted VMX.
12540 *
12541 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12542 * but single-stepping through the hypervisor debugger.
12543 *
12544 * @returns Strict VBox status code (i.e. informational status codes too).
12545 * @param pVCpu The cross context virtual CPU structure.
12546 * @param pcLoops Pointer to the number of executed loops.
12547 *
12548 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12549 */
12550static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12551{
12552 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12553 Assert(pcLoops);
12554 Assert(*pcLoops <= cMaxResumeLoops);
12555
12556 VMXTRANSIENT VmxTransient;
12557 RT_ZERO(VmxTransient);
12558 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12559
12560 /* Set HMCPU indicators. */
12561 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12562 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12563 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12564 pVCpu->hmr0.s.fUsingDebugLoop = true;
12565
12566 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12567 VMXRUNDBGSTATE DbgState;
12568 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12569 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12570
12571 /*
12572 * The loop.
12573 */
12574 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12575 for (;;)
12576 {
12577 Assert(!HMR0SuspendPending());
12578 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12579 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12580 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12581
12582 /* Set up VM-execution controls the next two can respond to. */
12583 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12584
12585 /*
12586 * Preparatory work for running guest code, this may force us to
12587 * return to ring-3.
12588 *
12589 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12590 */
12591 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12592 if (rcStrict != VINF_SUCCESS)
12593 break;
12594
12595 /* Interrupts are disabled at this point! */
12596 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12597
12598 /* Override any obnoxious code in the above two calls. */
12599 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12600
12601 /*
12602 * Finally execute the guest.
12603 */
12604 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12605
12606 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12607 /* Interrupts are re-enabled at this point! */
12608
12609 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12610 if (RT_SUCCESS(rcRun))
12611 { /* very likely */ }
12612 else
12613 {
12614 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12615 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12616 return rcRun;
12617 }
12618
12619 /* Profile the VM-exit. */
12620 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12621 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12622 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12623 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12624 HMVMX_START_EXIT_DISPATCH_PROF();
12625
12626 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12627
12628 /*
12629 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12630 */
12631 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12632 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12633 if (rcStrict != VINF_SUCCESS)
12634 break;
12635 if (++(*pcLoops) > cMaxResumeLoops)
12636 {
12637 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12638 rcStrict = VINF_EM_RAW_INTERRUPT;
12639 break;
12640 }
12641
12642 /*
12643 * Stepping: Did the RIP change, if so, consider it a single step.
12644 * Otherwise, make sure one of the TFs gets set.
12645 */
12646 if (fStepping)
12647 {
12648 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12649 AssertRC(rc);
12650 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12651 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12652 {
12653 rcStrict = VINF_EM_DBG_STEPPED;
12654 break;
12655 }
12656 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12657 }
12658
12659 /*
12660 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12661 */
12662 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12663 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12664
12665 /* Restore all controls applied by hmR0VmxPreRunGuestDebugStateApply above. */
12666 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12667 Assert(rcStrict == VINF_SUCCESS);
12668 }
12669
12670 /*
12671 * Clear the X86_EFL_TF if necessary.
12672 */
12673 if (pVCpu->hmr0.s.fClearTrapFlag)
12674 {
12675 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12676 AssertRC(rc);
12677 pVCpu->hmr0.s.fClearTrapFlag = false;
12678 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12679 }
12680 /** @todo there seems to be issues with the resume flag when the monitor trap
12681 * flag is pending without being used. Seen early in bios init when
12682 * accessing APIC page in protected mode. */
12683
12684 /* Restore HMCPU indicators. */
12685 pVCpu->hmr0.s.fUsingDebugLoop = false;
12686 pVCpu->hmr0.s.fDebugWantRdTscExit = false;
12687 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12688
12689 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12690 return rcStrict;
12691}
12692
12693
12694/** @} */
12695
12696
12697/**
12698 * Checks if any expensive dtrace probes are enabled and we should go to the
12699 * debug loop.
12700 *
12701 * @returns true if we should use debug loop, false if not.
12702 */
12703static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12704{
12705 /* It's probably faster to OR the raw 32-bit counter variables together.
12706 Since the variables are in an array and the probes are next to one
12707 another (more or less), we have good locality. So, better read
12708 eight-nine cache lines ever time and only have one conditional, than
12709 128+ conditionals, right? */
12710 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12711 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12712 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12713 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12714 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12715 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12716 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12717 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12718 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12719 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12720 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12721 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12722 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12723 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12724 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12725 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12726 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12727 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12728 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12729 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12730 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12731 ) != 0
12732 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12733 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12734 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12735 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12736 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12737 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12738 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12739 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12740 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12741 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12742 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12743 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12744 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12745 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12746 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12747 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12748 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12749 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12750 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12751 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12752 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12753 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12754 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12755 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12756 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12757 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12758 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12759 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12760 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12761 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12762 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12763 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12764 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12765 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12766 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12767 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12768 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12769 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12770 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12771 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12772 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12773 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12774 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12775 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12776 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12777 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12778 ) != 0
12779 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12780 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12781 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12782 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12783 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12784 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12785 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12786 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12787 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12788 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12789 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12790 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12791 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12792 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12793 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12794 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12795 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12796 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12797 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12798 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12799 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12800 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12801 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12802 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12803 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12804 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12805 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12806 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12807 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12808 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12809 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12810 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12811 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12812 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12813 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12814 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12815 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12816 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12817 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12818 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12819 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12820 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12821 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12822 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12823 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12824 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12825 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12826 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12827 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12828 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12829 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12830 ) != 0;
12831}
12832
12833
12834/**
12835 * Runs the guest using hardware-assisted VMX.
12836 *
12837 * @returns Strict VBox status code (i.e. informational status codes too).
12838 * @param pVCpu The cross context virtual CPU structure.
12839 */
12840VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12841{
12842 AssertPtr(pVCpu);
12843 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12844 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12845 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12846 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12847
12848 VBOXSTRICTRC rcStrict;
12849 uint32_t cLoops = 0;
12850 for (;;)
12851 {
12852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12853 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12854#else
12855 NOREF(pCtx);
12856 bool const fInNestedGuestMode = false;
12857#endif
12858 if (!fInNestedGuestMode)
12859 {
12860 if ( !pVCpu->hm.s.fUseDebugLoop
12861 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12862 && !DBGFIsStepping(pVCpu)
12863 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12864 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12865 else
12866 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12867 }
12868#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12869 else
12870 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12871
12872 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12873 {
12874 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12875 continue;
12876 }
12877 if (rcStrict == VINF_VMX_VMEXIT)
12878 {
12879 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12880 continue;
12881 }
12882#endif
12883 break;
12884 }
12885
12886 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12887 switch (rcLoop)
12888 {
12889 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12890 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12891 }
12892
12893 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12894 if (RT_FAILURE(rc2))
12895 {
12896 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12897 rcStrict = rc2;
12898 }
12899 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12900 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12901 return rcStrict;
12902}
12903
12904
12905#ifndef HMVMX_USE_FUNCTION_TABLE
12906/**
12907 * Handles a guest VM-exit from hardware-assisted VMX execution.
12908 *
12909 * @returns Strict VBox status code (i.e. informational status codes too).
12910 * @param pVCpu The cross context virtual CPU structure.
12911 * @param pVmxTransient The VMX-transient structure.
12912 */
12913DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12914{
12915#ifdef DEBUG_ramshankar
12916# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12917 do { \
12918 if (a_fSave != 0) \
12919 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12920 VBOXSTRICTRC rcStrict = a_CallExpr; \
12921 if (a_fSave != 0) \
12922 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12923 return rcStrict; \
12924 } while (0)
12925#else
12926# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12927#endif
12928 uint32_t const uExitReason = pVmxTransient->uExitReason;
12929 switch (uExitReason)
12930 {
12931 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12932 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12933 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12934 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12935 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12936 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12937 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12938 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12939 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12940 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12941 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12942 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12943 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12944 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12945 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12946 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12947 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12948 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12949 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12950 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12951 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12952 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12953 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12954 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12955 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12956 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12957 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12958 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12959 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12960 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12961#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12962 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12963 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12964 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12965 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12966 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12967 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12968 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12969 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12970 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12971 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12972 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12973#else
12974 case VMX_EXIT_VMCLEAR:
12975 case VMX_EXIT_VMLAUNCH:
12976 case VMX_EXIT_VMPTRLD:
12977 case VMX_EXIT_VMPTRST:
12978 case VMX_EXIT_VMREAD:
12979 case VMX_EXIT_VMRESUME:
12980 case VMX_EXIT_VMWRITE:
12981 case VMX_EXIT_VMXOFF:
12982 case VMX_EXIT_VMXON:
12983 case VMX_EXIT_INVVPID:
12984 case VMX_EXIT_INVEPT:
12985 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12986#endif
12987
12988 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12989 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12990 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12991
12992 case VMX_EXIT_INIT_SIGNAL:
12993 case VMX_EXIT_SIPI:
12994 case VMX_EXIT_IO_SMI:
12995 case VMX_EXIT_SMI:
12996 case VMX_EXIT_ERR_MSR_LOAD:
12997 case VMX_EXIT_ERR_MACHINE_CHECK:
12998 case VMX_EXIT_PML_FULL:
12999 case VMX_EXIT_VIRTUALIZED_EOI:
13000 case VMX_EXIT_GDTR_IDTR_ACCESS:
13001 case VMX_EXIT_LDTR_TR_ACCESS:
13002 case VMX_EXIT_APIC_WRITE:
13003 case VMX_EXIT_RDRAND:
13004 case VMX_EXIT_RSM:
13005 case VMX_EXIT_VMFUNC:
13006 case VMX_EXIT_ENCLS:
13007 case VMX_EXIT_RDSEED:
13008 case VMX_EXIT_XSAVES:
13009 case VMX_EXIT_XRSTORS:
13010 case VMX_EXIT_UMWAIT:
13011 case VMX_EXIT_TPAUSE:
13012 default:
13013 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13014 }
13015#undef VMEXIT_CALL_RET
13016}
13017#endif /* !HMVMX_USE_FUNCTION_TABLE */
13018
13019
13020#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13021/**
13022 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13023 *
13024 * @returns Strict VBox status code (i.e. informational status codes too).
13025 * @param pVCpu The cross context virtual CPU structure.
13026 * @param pVmxTransient The VMX-transient structure.
13027 */
13028DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13029{
13030 uint32_t const uExitReason = pVmxTransient->uExitReason;
13031 switch (uExitReason)
13032 {
13033 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13034 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13035 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13036 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13037 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13038
13039 /*
13040 * We shouldn't direct host physical interrupts to the nested-guest.
13041 */
13042 case VMX_EXIT_EXT_INT:
13043 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13044
13045 /*
13046 * Instructions that cause VM-exits unconditionally or the condition is
13047 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13048 * happens, it's guaranteed to be a nested-guest VM-exit).
13049 *
13050 * - Provides VM-exit instruction length ONLY.
13051 */
13052 case VMX_EXIT_CPUID: /* Unconditional. */
13053 case VMX_EXIT_VMCALL:
13054 case VMX_EXIT_GETSEC:
13055 case VMX_EXIT_INVD:
13056 case VMX_EXIT_XSETBV:
13057 case VMX_EXIT_VMLAUNCH:
13058 case VMX_EXIT_VMRESUME:
13059 case VMX_EXIT_VMXOFF:
13060 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
13061 case VMX_EXIT_VMFUNC:
13062 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13063
13064 /*
13065 * Instructions that cause VM-exits unconditionally or the condition is
13066 * always is taken solely from the nested hypervisor (meaning if the VM-exit
13067 * happens, it's guaranteed to be a nested-guest VM-exit).
13068 *
13069 * - Provides VM-exit instruction length.
13070 * - Provides VM-exit information.
13071 * - Optionally provides Exit qualification.
13072 *
13073 * Since Exit qualification is 0 for all VM-exits where it is not
13074 * applicable, reading and passing it to the guest should produce
13075 * defined behavior.
13076 *
13077 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13078 */
13079 case VMX_EXIT_INVEPT: /* Unconditional. */
13080 case VMX_EXIT_INVVPID:
13081 case VMX_EXIT_VMCLEAR:
13082 case VMX_EXIT_VMPTRLD:
13083 case VMX_EXIT_VMPTRST:
13084 case VMX_EXIT_VMXON:
13085 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
13086 case VMX_EXIT_LDTR_TR_ACCESS:
13087 case VMX_EXIT_RDRAND:
13088 case VMX_EXIT_RDSEED:
13089 case VMX_EXIT_XSAVES:
13090 case VMX_EXIT_XRSTORS:
13091 case VMX_EXIT_UMWAIT:
13092 case VMX_EXIT_TPAUSE:
13093 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13094
13095 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13096 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13097 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13098 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13099 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13100 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13101 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13102 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13103 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13104 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13105 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13106 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13107 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13108 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13109 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13110 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13111 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13112 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13113 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13114
13115 case VMX_EXIT_PREEMPT_TIMER:
13116 {
13117 /** @todo NSTVMX: Preempt timer. */
13118 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13119 }
13120
13121 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13122 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13123
13124 case VMX_EXIT_VMREAD:
13125 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13126
13127 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13128 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13129
13130 case VMX_EXIT_INIT_SIGNAL:
13131 case VMX_EXIT_SIPI:
13132 case VMX_EXIT_IO_SMI:
13133 case VMX_EXIT_SMI:
13134 case VMX_EXIT_ERR_MSR_LOAD:
13135 case VMX_EXIT_ERR_MACHINE_CHECK:
13136 case VMX_EXIT_PML_FULL:
13137 case VMX_EXIT_RSM:
13138 default:
13139 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13140 }
13141}
13142#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13143
13144
13145/** @name VM-exit helpers.
13146 * @{
13147 */
13148/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13149/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13150/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13151
13152/** Macro for VM-exits called unexpectedly. */
13153#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13154 do { \
13155 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13156 return VERR_VMX_UNEXPECTED_EXIT; \
13157 } while (0)
13158
13159#ifdef VBOX_STRICT
13160/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13161# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13162 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13163
13164# define HMVMX_ASSERT_PREEMPT_CPUID() \
13165 do { \
13166 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13167 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13168 } while (0)
13169
13170# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13171 do { \
13172 AssertPtr((a_pVCpu)); \
13173 AssertPtr((a_pVmxTransient)); \
13174 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13175 Assert((a_pVmxTransient)->pVmcsInfo); \
13176 Assert(ASMIntAreEnabled()); \
13177 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13178 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13179 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13180 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13181 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13182 HMVMX_ASSERT_PREEMPT_CPUID(); \
13183 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13184 } while (0)
13185
13186# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13187 do { \
13188 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13189 Assert((a_pVmxTransient)->fIsNestedGuest); \
13190 } while (0)
13191
13192# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13193 do { \
13194 Log4Func(("\n")); \
13195 } while (0)
13196#else
13197# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13198 do { \
13199 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13200 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13201 } while (0)
13202
13203# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13204 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13205
13206# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13207#endif
13208
13209#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13210/** Macro that does the necessary privilege checks and intercepted VM-exits for
13211 * guests that attempted to execute a VMX instruction. */
13212# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13213 do \
13214 { \
13215 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13216 if (rcStrictTmp == VINF_SUCCESS) \
13217 { /* likely */ } \
13218 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13219 { \
13220 Assert((a_pVCpu)->hm.s.Event.fPending); \
13221 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13222 return VINF_SUCCESS; \
13223 } \
13224 else \
13225 { \
13226 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13227 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13228 } \
13229 } while (0)
13230
13231/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13232# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13233 do \
13234 { \
13235 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13236 (a_pGCPtrEffAddr)); \
13237 if (rcStrictTmp == VINF_SUCCESS) \
13238 { /* likely */ } \
13239 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13240 { \
13241 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13242 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13243 NOREF(uXcptTmp); \
13244 return VINF_SUCCESS; \
13245 } \
13246 else \
13247 { \
13248 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13249 return rcStrictTmp; \
13250 } \
13251 } while (0)
13252#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13253
13254
13255/**
13256 * Advances the guest RIP by the specified number of bytes.
13257 *
13258 * @param pVCpu The cross context virtual CPU structure.
13259 * @param cbInstr Number of bytes to advance the RIP by.
13260 *
13261 * @remarks No-long-jump zone!!!
13262 */
13263DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
13264{
13265 /* Advance the RIP. */
13266 pVCpu->cpum.GstCtx.rip += cbInstr;
13267 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13268
13269 /* Update interrupt inhibition. */
13270 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13271 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13272 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13273}
13274
13275
13276/**
13277 * Advances the guest RIP after reading it from the VMCS.
13278 *
13279 * @returns VBox status code, no informational status codes.
13280 * @param pVCpu The cross context virtual CPU structure.
13281 * @param pVmxTransient The VMX-transient structure.
13282 *
13283 * @remarks No-long-jump zone!!!
13284 */
13285static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13286{
13287 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13288 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13289 AssertRCReturn(rc, rc);
13290
13291 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
13292 return VINF_SUCCESS;
13293}
13294
13295
13296/**
13297 * Handle a condition that occurred while delivering an event through the guest or
13298 * nested-guest IDT.
13299 *
13300 * @returns Strict VBox status code (i.e. informational status codes too).
13301 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13302 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13303 * to continue execution of the guest which will delivery the \#DF.
13304 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13305 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13306 *
13307 * @param pVCpu The cross context virtual CPU structure.
13308 * @param pVmxTransient The VMX-transient structure.
13309 *
13310 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13311 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13312 * is due to an EPT violation, PML full or SPP-related event.
13313 *
13314 * @remarks No-long-jump zone!!!
13315 */
13316static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13317{
13318 Assert(!pVCpu->hm.s.Event.fPending);
13319 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13320 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13321 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13322 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13323 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13324
13325 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13326 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13327 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13328 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13329 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13330 {
13331 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13332 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13333
13334 /*
13335 * If the event was a software interrupt (generated with INT n) or a software exception
13336 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13337 * can handle the VM-exit and continue guest execution which will re-execute the
13338 * instruction rather than re-injecting the exception, as that can cause premature
13339 * trips to ring-3 before injection and involve TRPM which currently has no way of
13340 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13341 * the problem).
13342 */
13343 IEMXCPTRAISE enmRaise;
13344 IEMXCPTRAISEINFO fRaiseInfo;
13345 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13346 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13347 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13348 {
13349 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13350 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13351 }
13352 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13353 {
13354 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13355 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13356 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13357
13358 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13359 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13360
13361 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13362
13363 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13364 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13365 {
13366 pVmxTransient->fVectoringPF = true;
13367 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13368 }
13369 }
13370 else
13371 {
13372 /*
13373 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13374 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13375 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13376 */
13377 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13378 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13379 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13380 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13381 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13382 }
13383
13384 /*
13385 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13386 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13387 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13388 * subsequent VM-entry would fail, see @bugref{7445}.
13389 *
13390 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13391 */
13392 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13393 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13394 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13395 && CPUMIsGuestNmiBlocking(pVCpu))
13396 {
13397 CPUMSetGuestNmiBlocking(pVCpu, false);
13398 }
13399
13400 switch (enmRaise)
13401 {
13402 case IEMXCPTRAISE_CURRENT_XCPT:
13403 {
13404 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13405 Assert(rcStrict == VINF_SUCCESS);
13406 break;
13407 }
13408
13409 case IEMXCPTRAISE_PREV_EVENT:
13410 {
13411 uint32_t u32ErrCode;
13412 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13413 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13414 else
13415 u32ErrCode = 0;
13416
13417 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13418 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13419 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13420 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13421
13422 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13423 pVCpu->hm.s.Event.u32ErrCode));
13424 Assert(rcStrict == VINF_SUCCESS);
13425 break;
13426 }
13427
13428 case IEMXCPTRAISE_REEXEC_INSTR:
13429 Assert(rcStrict == VINF_SUCCESS);
13430 break;
13431
13432 case IEMXCPTRAISE_DOUBLE_FAULT:
13433 {
13434 /*
13435 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13436 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13437 */
13438 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13439 {
13440 pVmxTransient->fVectoringDoublePF = true;
13441 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13442 pVCpu->cpum.GstCtx.cr2));
13443 rcStrict = VINF_SUCCESS;
13444 }
13445 else
13446 {
13447 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13448 hmR0VmxSetPendingXcptDF(pVCpu);
13449 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13450 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13451 rcStrict = VINF_HM_DOUBLE_FAULT;
13452 }
13453 break;
13454 }
13455
13456 case IEMXCPTRAISE_TRIPLE_FAULT:
13457 {
13458 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13459 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13460 rcStrict = VINF_EM_RESET;
13461 break;
13462 }
13463
13464 case IEMXCPTRAISE_CPU_HANG:
13465 {
13466 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13467 rcStrict = VERR_EM_GUEST_CPU_HANG;
13468 break;
13469 }
13470
13471 default:
13472 {
13473 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13474 rcStrict = VERR_VMX_IPE_2;
13475 break;
13476 }
13477 }
13478 }
13479 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13480 && !CPUMIsGuestNmiBlocking(pVCpu))
13481 {
13482 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13483 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13484 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13485 {
13486 /*
13487 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13488 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13489 * that virtual NMIs remain blocked until the IRET execution is completed.
13490 *
13491 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13492 */
13493 CPUMSetGuestNmiBlocking(pVCpu, true);
13494 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13495 }
13496 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13497 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13498 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13499 {
13500 /*
13501 * Execution of IRET caused an EPT violation, page-modification log-full event or
13502 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13503 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13504 * that virtual NMIs remain blocked until the IRET execution is completed.
13505 *
13506 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13507 */
13508 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13509 {
13510 CPUMSetGuestNmiBlocking(pVCpu, true);
13511 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13512 }
13513 }
13514 }
13515
13516 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13517 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13518 return rcStrict;
13519}
13520
13521
13522#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13523/**
13524 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13525 * guest attempting to execute a VMX instruction.
13526 *
13527 * @returns Strict VBox status code (i.e. informational status codes too).
13528 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13529 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13530 *
13531 * @param pVCpu The cross context virtual CPU structure.
13532 * @param uExitReason The VM-exit reason.
13533 *
13534 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13535 * @remarks No-long-jump zone!!!
13536 */
13537static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13538{
13539 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13540 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13541
13542 /*
13543 * The physical CPU would have already checked the CPU mode/code segment.
13544 * We shall just assert here for paranoia.
13545 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13546 */
13547 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13548 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13549 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13550
13551 if (uExitReason == VMX_EXIT_VMXON)
13552 {
13553 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13554
13555 /*
13556 * We check CR4.VMXE because it is required to be always set while in VMX operation
13557 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13558 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13559 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13560 */
13561 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13562 {
13563 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13564 hmR0VmxSetPendingXcptUD(pVCpu);
13565 return VINF_HM_PENDING_XCPT;
13566 }
13567 }
13568 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13569 {
13570 /*
13571 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13572 * (other than VMXON), we need to raise a #UD.
13573 */
13574 Log4Func(("Not in VMX root mode -> #UD\n"));
13575 hmR0VmxSetPendingXcptUD(pVCpu);
13576 return VINF_HM_PENDING_XCPT;
13577 }
13578
13579 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13580 return VINF_SUCCESS;
13581}
13582
13583
13584/**
13585 * Decodes the memory operand of an instruction that caused a VM-exit.
13586 *
13587 * The Exit qualification field provides the displacement field for memory
13588 * operand instructions, if any.
13589 *
13590 * @returns Strict VBox status code (i.e. informational status codes too).
13591 * @retval VINF_SUCCESS if the operand was successfully decoded.
13592 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13593 * operand.
13594 * @param pVCpu The cross context virtual CPU structure.
13595 * @param uExitInstrInfo The VM-exit instruction information field.
13596 * @param enmMemAccess The memory operand's access type (read or write).
13597 * @param GCPtrDisp The instruction displacement field, if any. For
13598 * RIP-relative addressing pass RIP + displacement here.
13599 * @param pGCPtrMem Where to store the effective destination memory address.
13600 *
13601 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13602 * virtual-8086 mode hence skips those checks while verifying if the
13603 * segment is valid.
13604 */
13605static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13606 PRTGCPTR pGCPtrMem)
13607{
13608 Assert(pGCPtrMem);
13609 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13610 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13611 | CPUMCTX_EXTRN_CR0);
13612
13613 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13614 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13615 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13616
13617 VMXEXITINSTRINFO ExitInstrInfo;
13618 ExitInstrInfo.u = uExitInstrInfo;
13619 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13620 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13621 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13622 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13623 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13624 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13625 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13626 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13627 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13628
13629 /*
13630 * Validate instruction information.
13631 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13632 */
13633 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13634 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13635 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13636 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13637 AssertLogRelMsgReturn(fIsMemOperand,
13638 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13639
13640 /*
13641 * Compute the complete effective address.
13642 *
13643 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13644 * See AMD spec. 4.5.2 "Segment Registers".
13645 */
13646 RTGCPTR GCPtrMem = GCPtrDisp;
13647 if (fBaseRegValid)
13648 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13649 if (fIdxRegValid)
13650 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13651
13652 RTGCPTR const GCPtrOff = GCPtrMem;
13653 if ( !fIsLongMode
13654 || iSegReg >= X86_SREG_FS)
13655 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13656 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13657
13658 /*
13659 * Validate effective address.
13660 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13661 */
13662 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13663 Assert(cbAccess > 0);
13664 if (fIsLongMode)
13665 {
13666 if (X86_IS_CANONICAL(GCPtrMem))
13667 {
13668 *pGCPtrMem = GCPtrMem;
13669 return VINF_SUCCESS;
13670 }
13671
13672 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13673 * "Data Limit Checks in 64-bit Mode". */
13674 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13675 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13676 return VINF_HM_PENDING_XCPT;
13677 }
13678
13679 /*
13680 * This is a watered down version of iemMemApplySegment().
13681 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13682 * and segment CPL/DPL checks are skipped.
13683 */
13684 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13685 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13686 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13687
13688 /* Check if the segment is present and usable. */
13689 if ( pSel->Attr.n.u1Present
13690 && !pSel->Attr.n.u1Unusable)
13691 {
13692 Assert(pSel->Attr.n.u1DescType);
13693 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13694 {
13695 /* Check permissions for the data segment. */
13696 if ( enmMemAccess == VMXMEMACCESS_WRITE
13697 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13698 {
13699 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13700 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13701 return VINF_HM_PENDING_XCPT;
13702 }
13703
13704 /* Check limits if it's a normal data segment. */
13705 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13706 {
13707 if ( GCPtrFirst32 > pSel->u32Limit
13708 || GCPtrLast32 > pSel->u32Limit)
13709 {
13710 Log4Func(("Data segment limit exceeded. "
13711 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13712 GCPtrLast32, pSel->u32Limit));
13713 if (iSegReg == X86_SREG_SS)
13714 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13715 else
13716 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13717 return VINF_HM_PENDING_XCPT;
13718 }
13719 }
13720 else
13721 {
13722 /* Check limits if it's an expand-down data segment.
13723 Note! The upper boundary is defined by the B bit, not the G bit! */
13724 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13725 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13726 {
13727 Log4Func(("Expand-down data segment limit exceeded. "
13728 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13729 GCPtrLast32, pSel->u32Limit));
13730 if (iSegReg == X86_SREG_SS)
13731 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13732 else
13733 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13734 return VINF_HM_PENDING_XCPT;
13735 }
13736 }
13737 }
13738 else
13739 {
13740 /* Check permissions for the code segment. */
13741 if ( enmMemAccess == VMXMEMACCESS_WRITE
13742 || ( enmMemAccess == VMXMEMACCESS_READ
13743 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13744 {
13745 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13746 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13747 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13748 return VINF_HM_PENDING_XCPT;
13749 }
13750
13751 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13752 if ( GCPtrFirst32 > pSel->u32Limit
13753 || GCPtrLast32 > pSel->u32Limit)
13754 {
13755 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13756 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13757 if (iSegReg == X86_SREG_SS)
13758 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13759 else
13760 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13761 return VINF_HM_PENDING_XCPT;
13762 }
13763 }
13764 }
13765 else
13766 {
13767 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13768 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13769 return VINF_HM_PENDING_XCPT;
13770 }
13771
13772 *pGCPtrMem = GCPtrMem;
13773 return VINF_SUCCESS;
13774}
13775#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13776
13777
13778/**
13779 * VM-exit helper for LMSW.
13780 */
13781static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13782{
13783 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13784 AssertRCReturn(rc, rc);
13785
13786 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13787 AssertMsg( rcStrict == VINF_SUCCESS
13788 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13789
13790 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
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
13797 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13798 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13799 return rcStrict;
13800}
13801
13802
13803/**
13804 * VM-exit helper for CLTS.
13805 */
13806static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13807{
13808 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13809 AssertRCReturn(rc, rc);
13810
13811 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13812 AssertMsg( rcStrict == VINF_SUCCESS
13813 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13814
13815 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13816 if (rcStrict == VINF_IEM_RAISED_XCPT)
13817 {
13818 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13819 rcStrict = VINF_SUCCESS;
13820 }
13821
13822 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13823 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13824 return rcStrict;
13825}
13826
13827
13828/**
13829 * VM-exit helper for MOV from CRx (CRx read).
13830 */
13831static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13832{
13833 Assert(iCrReg < 16);
13834 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13835
13836 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13837 AssertRCReturn(rc, rc);
13838
13839 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13840 AssertMsg( rcStrict == VINF_SUCCESS
13841 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13842
13843 if (iGReg == X86_GREG_xSP)
13844 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13845 else
13846 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13847#ifdef VBOX_WITH_STATISTICS
13848 switch (iCrReg)
13849 {
13850 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13851 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13852 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13853 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13854 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13855 }
13856#endif
13857 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13858 return rcStrict;
13859}
13860
13861
13862/**
13863 * VM-exit helper for MOV to CRx (CRx write).
13864 */
13865static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13866{
13867 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13868 AssertRCReturn(rc, rc);
13869
13870 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13871 AssertMsg( rcStrict == VINF_SUCCESS
13872 || rcStrict == VINF_IEM_RAISED_XCPT
13873 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13874
13875 switch (iCrReg)
13876 {
13877 case 0:
13878 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13879 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13880 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13881 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13882 break;
13883
13884 case 2:
13885 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13886 /* Nothing to do here, CR2 it's not part of the VMCS. */
13887 break;
13888
13889 case 3:
13890 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13891 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13892 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13893 break;
13894
13895 case 4:
13896 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13897 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13898 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13899 pVCpu->cpum.GstCtx.cr4, pVCpu->hmr0.s.fLoadSaveGuestXcr0));
13900 break;
13901
13902 case 8:
13903 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13904 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13905 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13906 break;
13907
13908 default:
13909 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13910 break;
13911 }
13912
13913 if (rcStrict == VINF_IEM_RAISED_XCPT)
13914 {
13915 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13916 rcStrict = VINF_SUCCESS;
13917 }
13918 return rcStrict;
13919}
13920
13921
13922/**
13923 * VM-exit exception handler for \#PF (Page-fault exception).
13924 *
13925 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13926 */
13927static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13928{
13929 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13930 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13931 hmR0VmxReadExitQualVmcs(pVmxTransient);
13932
13933 if (!pVM->hm.s.fNestedPaging)
13934 { /* likely */ }
13935 else
13936 {
13937#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13938 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hmr0.s.fUsingDebugLoop);
13939#endif
13940 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13941 if (!pVmxTransient->fVectoringDoublePF)
13942 {
13943 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13944 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13945 }
13946 else
13947 {
13948 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13949 Assert(!pVmxTransient->fIsNestedGuest);
13950 hmR0VmxSetPendingXcptDF(pVCpu);
13951 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13952 }
13953 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13954 return VINF_SUCCESS;
13955 }
13956
13957 Assert(!pVmxTransient->fIsNestedGuest);
13958
13959 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13960 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13961 if (pVmxTransient->fVectoringPF)
13962 {
13963 Assert(pVCpu->hm.s.Event.fPending);
13964 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13965 }
13966
13967 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13968 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13969 AssertRCReturn(rc, rc);
13970
13971 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13972 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13973
13974 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13975 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13976
13977 Log4Func(("#PF: rc=%Rrc\n", rc));
13978 if (rc == VINF_SUCCESS)
13979 {
13980 /*
13981 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13982 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13983 */
13984 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13985 TRPMResetTrap(pVCpu);
13986 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13987 return rc;
13988 }
13989
13990 if (rc == VINF_EM_RAW_GUEST_TRAP)
13991 {
13992 if (!pVmxTransient->fVectoringDoublePF)
13993 {
13994 /* It's a guest page fault and needs to be reflected to the guest. */
13995 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13996 TRPMResetTrap(pVCpu);
13997 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13998 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13999 uGstErrorCode, pVmxTransient->uExitQual);
14000 }
14001 else
14002 {
14003 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14004 TRPMResetTrap(pVCpu);
14005 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14006 hmR0VmxSetPendingXcptDF(pVCpu);
14007 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14008 }
14009
14010 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14011 return VINF_SUCCESS;
14012 }
14013
14014 TRPMResetTrap(pVCpu);
14015 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14016 return rc;
14017}
14018
14019
14020/**
14021 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14022 *
14023 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14024 */
14025static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14026{
14027 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14028 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14029
14030 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14031 AssertRCReturn(rc, rc);
14032
14033 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14034 {
14035 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14036 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14037
14038 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14039 * provides VM-exit instruction length. If this causes problem later,
14040 * disassemble the instruction like it's done on AMD-V. */
14041 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14042 AssertRCReturn(rc2, rc2);
14043 return rc;
14044 }
14045
14046 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
14047 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14048 return VINF_SUCCESS;
14049}
14050
14051
14052/**
14053 * VM-exit exception handler for \#BP (Breakpoint exception).
14054 *
14055 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14056 */
14057static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14058{
14059 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14060 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14061
14062 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14063 AssertRCReturn(rc, rc);
14064
14065 if (!pVmxTransient->fIsNestedGuest)
14066 rc = DBGFTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14067 else
14068 rc = VINF_EM_RAW_GUEST_TRAP;
14069
14070 if (rc == VINF_EM_RAW_GUEST_TRAP)
14071 {
14072 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14073 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14074 rc = VINF_SUCCESS;
14075 }
14076
14077 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
14078 return rc;
14079}
14080
14081
14082/**
14083 * VM-exit exception handler for \#AC (Alignment-check exception).
14084 *
14085 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14086 */
14087static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14088{
14089 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14090 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14091
14092 /* Re-inject it. We'll detect any nesting before getting here. */
14093 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14094 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14095 return VINF_SUCCESS;
14096}
14097
14098
14099/**
14100 * VM-exit exception handler for \#DB (Debug exception).
14101 *
14102 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14103 */
14104static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14105{
14106 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14107 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14108
14109 /*
14110 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14111 */
14112 hmR0VmxReadExitQualVmcs(pVmxTransient);
14113
14114 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14115 uint64_t const uDR6 = X86_DR6_INIT_VAL
14116 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14117 | X86_DR6_BD | X86_DR6_BS));
14118
14119 int rc;
14120 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14121 if (!pVmxTransient->fIsNestedGuest)
14122 {
14123 rc = DBGFTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14124
14125 /*
14126 * Prevents stepping twice over the same instruction when the guest is stepping using
14127 * EFLAGS.TF and the hypervisor debugger is stepping using MTF.
14128 * Testcase: DOSQEMM, break (using "ba x 1") at cs:rip 0x70:0x774 and step (using "t").
14129 */
14130 if ( rc == VINF_EM_DBG_STEPPED
14131 && (pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MONITOR_TRAP_FLAG))
14132 {
14133 Assert(pVCpu->hm.s.fSingleInstruction);
14134 rc = VINF_EM_RAW_GUEST_TRAP;
14135 }
14136 }
14137 else
14138 rc = VINF_EM_RAW_GUEST_TRAP;
14139 Log6Func(("rc=%Rrc\n", rc));
14140 if (rc == VINF_EM_RAW_GUEST_TRAP)
14141 {
14142 /*
14143 * The exception was for the guest. Update DR6, DR7.GD and
14144 * IA32_DEBUGCTL.LBR before forwarding it.
14145 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14146 */
14147 VMMRZCallRing3Disable(pVCpu);
14148 HM_DISABLE_PREEMPT(pVCpu);
14149
14150 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14151 pCtx->dr[6] |= uDR6;
14152 if (CPUMIsGuestDebugStateActive(pVCpu))
14153 ASMSetDR6(pCtx->dr[6]);
14154
14155 HM_RESTORE_PREEMPT();
14156 VMMRZCallRing3Enable(pVCpu);
14157
14158 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14159 AssertRCReturn(rc, rc);
14160
14161 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14162 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
14163
14164 /* Paranoia. */
14165 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
14166 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14167
14168 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
14169 AssertRC(rc);
14170
14171 /*
14172 * Raise #DB in the guest.
14173 *
14174 * It is important to reflect exactly what the VM-exit gave us (preserving the
14175 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14176 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14177 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14178 *
14179 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14180 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14181 */
14182 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14183 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14184 return VINF_SUCCESS;
14185 }
14186
14187 /*
14188 * Not a guest trap, must be a hypervisor related debug event then.
14189 * Update DR6 in case someone is interested in it.
14190 */
14191 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14192 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14193 CPUMSetHyperDR6(pVCpu, uDR6);
14194
14195 return rc;
14196}
14197
14198
14199/**
14200 * Hacks its way around the lovely mesa driver's backdoor accesses.
14201 *
14202 * @sa hmR0SvmHandleMesaDrvGp.
14203 */
14204static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14205{
14206 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14207 RT_NOREF(pCtx);
14208
14209 /* For now we'll just skip the instruction. */
14210 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14211}
14212
14213
14214/**
14215 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14216 * backdoor logging w/o checking what it is running inside.
14217 *
14218 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14219 * backdoor port and magic numbers loaded in registers.
14220 *
14221 * @returns true if it is, false if it isn't.
14222 * @sa hmR0SvmIsMesaDrvGp.
14223 */
14224DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14225{
14226 /* 0xed: IN eAX,dx */
14227 uint8_t abInstr[1];
14228 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
14229 return false;
14230
14231 /* Check that it is #GP(0). */
14232 if (pVmxTransient->uExitIntErrorCode != 0)
14233 return false;
14234
14235 /* Check magic and port. */
14236 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14237 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14238 if (pCtx->rax != UINT32_C(0x564d5868))
14239 return false;
14240 if (pCtx->dx != UINT32_C(0x5658))
14241 return false;
14242
14243 /* Flat ring-3 CS. */
14244 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14245 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14246 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14247 if (pCtx->cs.Attr.n.u2Dpl != 3)
14248 return false;
14249 if (pCtx->cs.u64Base != 0)
14250 return false;
14251
14252 /* Check opcode. */
14253 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14254 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14255 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14256 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14257 if (RT_FAILURE(rc))
14258 return false;
14259 if (abInstr[0] != 0xed)
14260 return false;
14261
14262 return true;
14263}
14264
14265
14266/**
14267 * VM-exit exception handler for \#GP (General-protection exception).
14268 *
14269 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14270 */
14271static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14272{
14273 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14274 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14275
14276 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14277 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14278 PVMXVMCSINFOSHARED pVmcsInfoShared = pVmcsInfo->pShared;
14279 if (pVmcsInfoShared->RealMode.fRealOnV86Active)
14280 { /* likely */ }
14281 else
14282 {
14283#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14284 Assert(pVCpu->hmr0.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14285#endif
14286 /*
14287 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14288 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14289 */
14290 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14291 AssertRCReturn(rc, rc);
14292 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14293 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14294
14295 if ( pVmxTransient->fIsNestedGuest
14296 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14297 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14298 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14299 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14300 else
14301 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14302 return rc;
14303 }
14304
14305 Assert(CPUMIsGuestInRealModeEx(pCtx));
14306 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14307 Assert(!pVmxTransient->fIsNestedGuest);
14308
14309 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14310 AssertRCReturn(rc, rc);
14311
14312 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14313 if (rcStrict == VINF_SUCCESS)
14314 {
14315 if (!CPUMIsGuestInRealModeEx(pCtx))
14316 {
14317 /*
14318 * The guest is no longer in real-mode, check if we can continue executing the
14319 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14320 */
14321 pVmcsInfoShared->RealMode.fRealOnV86Active = false;
14322 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
14323 {
14324 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14325 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14326 }
14327 else
14328 {
14329 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14330 rcStrict = VINF_EM_RESCHEDULE;
14331 }
14332 }
14333 else
14334 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14335 }
14336 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14337 {
14338 rcStrict = VINF_SUCCESS;
14339 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14340 }
14341 return VBOXSTRICTRC_VAL(rcStrict);
14342}
14343
14344
14345/**
14346 * VM-exit exception handler wrapper for all other exceptions that are not handled
14347 * by a specific handler.
14348 *
14349 * This simply re-injects the exception back into the VM without any special
14350 * processing.
14351 *
14352 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14353 */
14354static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14355{
14356 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14357
14358#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14359 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14360 AssertMsg(pVCpu->hmr0.s.fUsingDebugLoop || pVmcsInfo->pShared->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14361 ("uVector=%#x u32XcptBitmap=%#X32\n",
14362 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14363 NOREF(pVmcsInfo);
14364#endif
14365
14366 /*
14367 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14368 * would have been handled while checking exits due to event delivery.
14369 */
14370 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14371
14372#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14373 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14374 AssertRCReturn(rc, rc);
14375 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14376#endif
14377
14378#ifdef VBOX_WITH_STATISTICS
14379 switch (uVector)
14380 {
14381 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14382 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14383 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14384 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14385 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14386 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14387 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14388 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14389 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14390 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14391 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14392 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14393 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14394 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14395 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14396 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14397 default:
14398 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14399 break;
14400 }
14401#endif
14402
14403 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14404 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14405 NOREF(uVector);
14406
14407 /* Re-inject the original exception into the guest. */
14408 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14409 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14410 return VINF_SUCCESS;
14411}
14412
14413
14414/**
14415 * VM-exit exception handler for all exceptions (except NMIs!).
14416 *
14417 * @remarks This may be called for both guests and nested-guests. Take care to not
14418 * make assumptions and avoid doing anything that is not relevant when
14419 * executing a nested-guest (e.g., Mesa driver hacks).
14420 */
14421static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14422{
14423 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14424
14425 /*
14426 * If this VM-exit occurred while delivering an event through the guest IDT, take
14427 * action based on the return code and additional hints (e.g. for page-faults)
14428 * that will be updated in the VMX transient structure.
14429 */
14430 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14431 if (rcStrict == VINF_SUCCESS)
14432 {
14433 /*
14434 * If an exception caused a VM-exit due to delivery of an event, the original
14435 * event may have to be re-injected into the guest. We shall reinject it and
14436 * continue guest execution. However, page-fault is a complicated case and
14437 * needs additional processing done in hmR0VmxExitXcptPF().
14438 */
14439 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14440 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14441 if ( !pVCpu->hm.s.Event.fPending
14442 || uVector == X86_XCPT_PF)
14443 {
14444 switch (uVector)
14445 {
14446 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14447 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14448 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14449 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14450 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14451 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14452 default:
14453 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14454 }
14455 }
14456 /* else: inject pending event before resuming guest execution. */
14457 }
14458 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14459 {
14460 Assert(pVCpu->hm.s.Event.fPending);
14461 rcStrict = VINF_SUCCESS;
14462 }
14463
14464 return rcStrict;
14465}
14466/** @} */
14467
14468
14469/** @name VM-exit handlers.
14470 * @{
14471 */
14472/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14473/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14474/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14475
14476/**
14477 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14478 */
14479HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14480{
14481 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14482 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14483 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14484 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14485 return VINF_SUCCESS;
14486 return VINF_EM_RAW_INTERRUPT;
14487}
14488
14489
14490/**
14491 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14492 * VM-exit.
14493 */
14494HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14495{
14496 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14497 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14498
14499 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14500
14501 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14502 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14503 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14504
14505 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14506 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14507 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14508 NOREF(pVmcsInfo);
14509
14510 VBOXSTRICTRC rcStrict;
14511 switch (uExitIntType)
14512 {
14513 /*
14514 * Host physical NMIs:
14515 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14516 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14517 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14518 *
14519 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14520 * See Intel spec. 27.5.5 "Updating Non-Register State".
14521 */
14522 case VMX_EXIT_INT_INFO_TYPE_NMI:
14523 {
14524 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14525 break;
14526 }
14527
14528 /*
14529 * Privileged software exceptions (#DB from ICEBP),
14530 * Software exceptions (#BP and #OF),
14531 * Hardware exceptions:
14532 * Process the required exceptions and resume guest execution if possible.
14533 */
14534 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14535 Assert(uVector == X86_XCPT_DB);
14536 RT_FALL_THRU();
14537 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14538 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14539 RT_FALL_THRU();
14540 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14541 {
14542 NOREF(uVector);
14543 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14544 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14545 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14546 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14547
14548 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14549 break;
14550 }
14551
14552 default:
14553 {
14554 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14555 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14556 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14557 break;
14558 }
14559 }
14560
14561 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14562 return rcStrict;
14563}
14564
14565
14566/**
14567 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14568 */
14569HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14570{
14571 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14572
14573 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14574 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14575 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14576
14577 /* Evaluate and deliver pending events and resume guest execution. */
14578 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14579 return VINF_SUCCESS;
14580}
14581
14582
14583/**
14584 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14585 */
14586HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14587{
14588 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14589
14590 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14591 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14592 {
14593 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14594 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14595 }
14596
14597 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14598
14599 /*
14600 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14601 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14602 */
14603 uint32_t fIntrState;
14604 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14605 AssertRC(rc);
14606 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14607 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14608 {
14609 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14610 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14611
14612 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14613 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14614 AssertRC(rc);
14615 }
14616
14617 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14618 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14619
14620 /* Evaluate and deliver pending events and resume guest execution. */
14621 return VINF_SUCCESS;
14622}
14623
14624
14625/**
14626 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14627 */
14628HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14629{
14630 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14631 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14632}
14633
14634
14635/**
14636 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14637 */
14638HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14639{
14640 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14641 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14642}
14643
14644
14645/**
14646 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14647 */
14648HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14649{
14650 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14651
14652 /*
14653 * Get the state we need and update the exit history entry.
14654 */
14655 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14656 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14657
14658 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14659 AssertRCReturn(rc, rc);
14660
14661 VBOXSTRICTRC rcStrict;
14662 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14663 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14664 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14665 if (!pExitRec)
14666 {
14667 /*
14668 * Regular CPUID instruction execution.
14669 */
14670 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14671 if (rcStrict == VINF_SUCCESS)
14672 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14673 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14674 {
14675 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14676 rcStrict = VINF_SUCCESS;
14677 }
14678 }
14679 else
14680 {
14681 /*
14682 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14683 */
14684 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14685 AssertRCReturn(rc2, rc2);
14686
14687 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14688 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14689
14690 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14691 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14692
14693 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14694 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14695 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14696 }
14697 return rcStrict;
14698}
14699
14700
14701/**
14702 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14703 */
14704HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14705{
14706 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14707
14708 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14709 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14710 AssertRCReturn(rc, rc);
14711
14712 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14713 return VINF_EM_RAW_EMULATE_INSTR;
14714
14715 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14716 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14717}
14718
14719
14720/**
14721 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14722 */
14723HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14724{
14725 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14726
14727 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14728 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14729 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14730 AssertRCReturn(rc, rc);
14731
14732 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14733 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14734 {
14735 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14736 we must reset offsetting on VM-entry. See @bugref{6634}. */
14737 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14738 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14739 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14740 }
14741 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14742 {
14743 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14744 rcStrict = VINF_SUCCESS;
14745 }
14746 return rcStrict;
14747}
14748
14749
14750/**
14751 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14752 */
14753HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14754{
14755 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14756
14757 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14758 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14759 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14760 AssertRCReturn(rc, rc);
14761
14762 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14763 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14764 {
14765 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14766 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14767 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14768 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14769 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14770 }
14771 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14772 {
14773 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14774 rcStrict = VINF_SUCCESS;
14775 }
14776 return rcStrict;
14777}
14778
14779
14780/**
14781 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14782 */
14783HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14784{
14785 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14786
14787 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14788 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14789 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14790 AssertRCReturn(rc, rc);
14791
14792 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14793 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14794 if (RT_LIKELY(rc == VINF_SUCCESS))
14795 {
14796 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14797 Assert(pVmxTransient->cbExitInstr == 2);
14798 }
14799 else
14800 {
14801 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14802 rc = VERR_EM_INTERPRETER;
14803 }
14804 return rc;
14805}
14806
14807
14808/**
14809 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14810 */
14811HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14812{
14813 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14814
14815 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14816 if (EMAreHypercallInstructionsEnabled(pVCpu))
14817 {
14818 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14819 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14820 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14821 AssertRCReturn(rc, rc);
14822
14823 /* Perform the hypercall. */
14824 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14825 if (rcStrict == VINF_SUCCESS)
14826 {
14827 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14828 AssertRCReturn(rc, rc);
14829 }
14830 else
14831 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14832 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14833 || RT_FAILURE(rcStrict));
14834
14835 /* If the hypercall changes anything other than guest's general-purpose registers,
14836 we would need to reload the guest changed bits here before VM-entry. */
14837 }
14838 else
14839 Log4Func(("Hypercalls not enabled\n"));
14840
14841 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14842 if (RT_FAILURE(rcStrict))
14843 {
14844 hmR0VmxSetPendingXcptUD(pVCpu);
14845 rcStrict = VINF_SUCCESS;
14846 }
14847
14848 return rcStrict;
14849}
14850
14851
14852/**
14853 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14854 */
14855HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14856{
14857 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14858 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hmr0.s.fUsingDebugLoop);
14859
14860 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14861 hmR0VmxReadExitQualVmcs(pVmxTransient);
14862 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14863 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14864 AssertRCReturn(rc, rc);
14865
14866 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14867
14868 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14869 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14870 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14871 {
14872 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14873 rcStrict = VINF_SUCCESS;
14874 }
14875 else
14876 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14877 VBOXSTRICTRC_VAL(rcStrict)));
14878 return rcStrict;
14879}
14880
14881
14882/**
14883 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14884 */
14885HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14886{
14887 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14888
14889 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14890 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14891 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14892 AssertRCReturn(rc, rc);
14893
14894 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14895 if (rcStrict == VINF_SUCCESS)
14896 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14897 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14898 {
14899 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14900 rcStrict = VINF_SUCCESS;
14901 }
14902
14903 return rcStrict;
14904}
14905
14906
14907/**
14908 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14909 */
14910HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14911{
14912 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14913
14914 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14915 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14916 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14917 AssertRCReturn(rc, rc);
14918
14919 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14920 if (RT_SUCCESS(rcStrict))
14921 {
14922 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14923 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14924 rcStrict = VINF_SUCCESS;
14925 }
14926
14927 return rcStrict;
14928}
14929
14930
14931/**
14932 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14933 * VM-exit.
14934 */
14935HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14936{
14937 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14938 return VINF_EM_RESET;
14939}
14940
14941
14942/**
14943 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14944 */
14945HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14946{
14947 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14948
14949 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14950 AssertRCReturn(rc, rc);
14951
14952 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14953 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14954 rc = VINF_SUCCESS;
14955 else
14956 rc = VINF_EM_HALT;
14957
14958 if (rc != VINF_SUCCESS)
14959 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14960 return rc;
14961}
14962
14963
14964/**
14965 * VM-exit handler for instructions that result in a \#UD exception delivered to
14966 * the guest.
14967 */
14968HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14969{
14970 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14971 hmR0VmxSetPendingXcptUD(pVCpu);
14972 return VINF_SUCCESS;
14973}
14974
14975
14976/**
14977 * VM-exit handler for expiry of the VMX-preemption timer.
14978 */
14979HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14980{
14981 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14982
14983 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14984 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14985
14986 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14987 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14988 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14989 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14990 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14991}
14992
14993
14994/**
14995 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14996 */
14997HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14998{
14999 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15000
15001 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15002 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15003 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15004 AssertRCReturn(rc, rc);
15005
15006 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
15007 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15008 : HM_CHANGED_RAISED_XCPT_MASK);
15009
15010 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15011 bool const fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15012 if (fLoadSaveGuestXcr0 != pVCpu->hmr0.s.fLoadSaveGuestXcr0)
15013 {
15014 pVCpu->hmr0.s.fLoadSaveGuestXcr0 = fLoadSaveGuestXcr0;
15015 hmR0VmxUpdateStartVmFunction(pVCpu);
15016 }
15017
15018 return rcStrict;
15019}
15020
15021
15022/**
15023 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15024 */
15025HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15026{
15027 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15028
15029 /** @todo Enable the new code after finding a reliably guest test-case. */
15030#if 1
15031 return VERR_EM_INTERPRETER;
15032#else
15033 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15034 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15035 hmR0VmxReadExitQualVmcs(pVmxTransient);
15036 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15037 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15038 AssertRCReturn(rc, rc);
15039
15040 /* Paranoia. Ensure this has a memory operand. */
15041 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
15042
15043 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
15044 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
15045 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
15046 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
15047
15048 RTGCPTR GCPtrDesc;
15049 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
15050
15051 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
15052 GCPtrDesc, uType);
15053 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15054 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15055 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15056 {
15057 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15058 rcStrict = VINF_SUCCESS;
15059 }
15060 return rcStrict;
15061#endif
15062}
15063
15064
15065/**
15066 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15067 * VM-exit.
15068 */
15069HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15070{
15071 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15072 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15073 AssertRCReturn(rc, rc);
15074
15075 rc = hmR0VmxCheckCachedVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15076 if (RT_FAILURE(rc))
15077 return rc;
15078
15079 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15080 NOREF(uInvalidReason);
15081
15082#ifdef VBOX_STRICT
15083 uint32_t fIntrState;
15084 uint64_t u64Val;
15085 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15086 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15087 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15088
15089 Log4(("uInvalidReason %u\n", uInvalidReason));
15090 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15091 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15092 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15093
15094 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
15095 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15096 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
15097 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
15098 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
15099 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
15100 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
15101 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15102 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
15103 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
15104 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
15105 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
15106 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15107 {
15108 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15109 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15110 }
15111 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
15112#endif
15113
15114 return VERR_VMX_INVALID_GUEST_STATE;
15115}
15116
15117/**
15118 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15119 */
15120HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15121{
15122 /*
15123 * Cumulative notes of all recognized but unexpected VM-exits.
15124 *
15125 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
15126 * nested-paging is used.
15127 *
15128 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15129 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15130 * this function (and thereby stop VM execution) for handling such instructions.
15131 *
15132 *
15133 * VMX_EXIT_INIT_SIGNAL:
15134 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15135 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15136 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15137 *
15138 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15139 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15140 * See Intel spec. "23.8 Restrictions on VMX operation".
15141 *
15142 * VMX_EXIT_SIPI:
15143 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15144 * activity state is used. We don't make use of it as our guests don't have direct
15145 * access to the host local APIC.
15146 *
15147 * See Intel spec. 25.3 "Other Causes of VM-exits".
15148 *
15149 * VMX_EXIT_IO_SMI:
15150 * VMX_EXIT_SMI:
15151 * This can only happen if we support dual-monitor treatment of SMI, which can be
15152 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15153 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15154 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15155 *
15156 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15157 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15158 *
15159 * VMX_EXIT_ERR_MSR_LOAD:
15160 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15161 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15162 * execution.
15163 *
15164 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15165 *
15166 * VMX_EXIT_ERR_MACHINE_CHECK:
15167 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15168 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15169 * #MC exception abort class exception is raised. We thus cannot assume a
15170 * reasonable chance of continuing any sort of execution and we bail.
15171 *
15172 * See Intel spec. 15.1 "Machine-check Architecture".
15173 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15174 *
15175 * VMX_EXIT_PML_FULL:
15176 * VMX_EXIT_VIRTUALIZED_EOI:
15177 * VMX_EXIT_APIC_WRITE:
15178 * We do not currently support any of these features and thus they are all unexpected
15179 * VM-exits.
15180 *
15181 * VMX_EXIT_GDTR_IDTR_ACCESS:
15182 * VMX_EXIT_LDTR_TR_ACCESS:
15183 * VMX_EXIT_RDRAND:
15184 * VMX_EXIT_RSM:
15185 * VMX_EXIT_VMFUNC:
15186 * VMX_EXIT_ENCLS:
15187 * VMX_EXIT_RDSEED:
15188 * VMX_EXIT_XSAVES:
15189 * VMX_EXIT_XRSTORS:
15190 * VMX_EXIT_UMWAIT:
15191 * VMX_EXIT_TPAUSE:
15192 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15193 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15194 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15195 *
15196 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15197 */
15198 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15199 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15200 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15201}
15202
15203
15204/**
15205 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15206 */
15207HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15208{
15209 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15210
15211 /** @todo Optimize this: We currently drag in the whole MSR state
15212 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15213 * MSRs required. That would require changes to IEM and possibly CPUM too.
15214 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15215 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15216 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15217 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15218 switch (idMsr)
15219 {
15220 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15221 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15222 }
15223
15224 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15225 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15226 AssertRCReturn(rc, rc);
15227
15228 Log4Func(("ecx=%#RX32\n", idMsr));
15229
15230#ifdef VBOX_STRICT
15231 Assert(!pVmxTransient->fIsNestedGuest);
15232 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15233 {
15234 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15235 && idMsr != MSR_K6_EFER)
15236 {
15237 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15238 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15239 }
15240 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15241 {
15242 Assert(pVmcsInfo->pvMsrBitmap);
15243 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15244 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15245 {
15246 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15247 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15248 }
15249 }
15250 }
15251#endif
15252
15253 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
15254 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15255 if (rcStrict == VINF_SUCCESS)
15256 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15257 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15258 {
15259 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15260 rcStrict = VINF_SUCCESS;
15261 }
15262 else
15263 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ || rcStrict == VINF_EM_TRIPLE_FAULT,
15264 ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15265
15266 return rcStrict;
15267}
15268
15269
15270/**
15271 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15272 */
15273HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15274{
15275 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15276
15277 /** @todo Optimize this: We currently drag in the whole MSR state
15278 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15279 * MSRs required. That would require changes to IEM and possibly CPUM too.
15280 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15281 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15282 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15283
15284 /*
15285 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15286 * Although we don't need to fetch the base as it will be overwritten shortly, while
15287 * loading guest-state we would also load the entire segment register including limit
15288 * and attributes and thus we need to load them here.
15289 */
15290 switch (idMsr)
15291 {
15292 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15293 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15294 }
15295
15296 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15297 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15298 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15299 AssertRCReturn(rc, rc);
15300
15301 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15302
15303 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
15304 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15305
15306 if (rcStrict == VINF_SUCCESS)
15307 {
15308 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15309
15310 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15311 if ( idMsr == MSR_IA32_APICBASE
15312 || ( idMsr >= MSR_IA32_X2APIC_START
15313 && idMsr <= MSR_IA32_X2APIC_END))
15314 {
15315 /*
15316 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15317 * When full APIC register virtualization is implemented we'll have to make
15318 * sure APIC state is saved from the VMCS before IEM changes it.
15319 */
15320 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15321 }
15322 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15323 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15324 else if (idMsr == MSR_K6_EFER)
15325 {
15326 /*
15327 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15328 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15329 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15330 */
15331 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15332 }
15333
15334 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15335 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15336 {
15337 switch (idMsr)
15338 {
15339 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15340 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15341 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15342 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15343 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15344 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15345 default:
15346 {
15347 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15348 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15349 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15350 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15351 break;
15352 }
15353 }
15354 }
15355#ifdef VBOX_STRICT
15356 else
15357 {
15358 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15359 switch (idMsr)
15360 {
15361 case MSR_IA32_SYSENTER_CS:
15362 case MSR_IA32_SYSENTER_EIP:
15363 case MSR_IA32_SYSENTER_ESP:
15364 case MSR_K8_FS_BASE:
15365 case MSR_K8_GS_BASE:
15366 {
15367 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15368 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15369 }
15370
15371 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15372 default:
15373 {
15374 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15375 {
15376 /* EFER MSR writes are always intercepted. */
15377 if (idMsr != MSR_K6_EFER)
15378 {
15379 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15380 idMsr));
15381 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15382 }
15383 }
15384
15385 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15386 {
15387 Assert(pVmcsInfo->pvMsrBitmap);
15388 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15389 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15390 {
15391 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15392 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15393 }
15394 }
15395 break;
15396 }
15397 }
15398 }
15399#endif /* VBOX_STRICT */
15400 }
15401 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15402 {
15403 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15404 rcStrict = VINF_SUCCESS;
15405 }
15406 else
15407 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE || rcStrict == VINF_EM_TRIPLE_FAULT,
15408 ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15409
15410 return rcStrict;
15411}
15412
15413
15414/**
15415 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15416 */
15417HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15418{
15419 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15420
15421 /** @todo The guest has likely hit a contended spinlock. We might want to
15422 * poke a schedule different guest VCPU. */
15423 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15424 if (RT_SUCCESS(rc))
15425 return VINF_EM_RAW_INTERRUPT;
15426
15427 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15428 return rc;
15429}
15430
15431
15432/**
15433 * VM-exit handler for when the TPR value is lowered below the specified
15434 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15435 */
15436HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15437{
15438 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15439 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15440
15441 /*
15442 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15443 * We'll re-evaluate pending interrupts and inject them before the next VM
15444 * entry so we can just continue execution here.
15445 */
15446 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15447 return VINF_SUCCESS;
15448}
15449
15450
15451/**
15452 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15453 * VM-exit.
15454 *
15455 * @retval VINF_SUCCESS when guest execution can continue.
15456 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15457 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15458 * incompatible guest state for VMX execution (real-on-v86 case).
15459 */
15460HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15461{
15462 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15463 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15464
15465 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15466 hmR0VmxReadExitQualVmcs(pVmxTransient);
15467 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15468
15469 VBOXSTRICTRC rcStrict;
15470 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15471 uint64_t const uExitQual = pVmxTransient->uExitQual;
15472 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15473 switch (uAccessType)
15474 {
15475 /*
15476 * MOV to CRx.
15477 */
15478 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15479 {
15480 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15481 AssertRCReturn(rc, rc);
15482
15483 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15484 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15485 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15486 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15487
15488 /*
15489 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15490 * - When nested paging isn't used.
15491 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15492 * - We are executing in the VM debug loop.
15493 */
15494 Assert( iCrReg != 3
15495 || !pVM->hm.s.fNestedPaging
15496 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15497 || pVCpu->hmr0.s.fUsingDebugLoop);
15498
15499 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15500 Assert( iCrReg != 8
15501 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15502
15503 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15504 AssertMsg( rcStrict == VINF_SUCCESS
15505 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15506
15507 /*
15508 * This is a kludge for handling switches back to real mode when we try to use
15509 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15510 * deal with special selector values, so we have to return to ring-3 and run
15511 * there till the selector values are V86 mode compatible.
15512 *
15513 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15514 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15515 * this function.
15516 */
15517 if ( iCrReg == 0
15518 && rcStrict == VINF_SUCCESS
15519 && !pVM->hm.s.vmx.fUnrestrictedGuest
15520 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15521 && (uOldCr0 & X86_CR0_PE)
15522 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15523 {
15524 /** @todo Check selectors rather than returning all the time. */
15525 Assert(!pVmxTransient->fIsNestedGuest);
15526 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15527 rcStrict = VINF_EM_RESCHEDULE_REM;
15528 }
15529 break;
15530 }
15531
15532 /*
15533 * MOV from CRx.
15534 */
15535 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15536 {
15537 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15538 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15539
15540 /*
15541 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15542 * - When nested paging isn't used.
15543 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15544 * - We are executing in the VM debug loop.
15545 */
15546 Assert( iCrReg != 3
15547 || !pVM->hm.s.fNestedPaging
15548 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15549 || pVCpu->hmr0.s.fLeaveDone);
15550
15551 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15552 Assert( iCrReg != 8
15553 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15554
15555 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15556 break;
15557 }
15558
15559 /*
15560 * CLTS (Clear Task-Switch Flag in CR0).
15561 */
15562 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15563 {
15564 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15565 break;
15566 }
15567
15568 /*
15569 * LMSW (Load Machine-Status Word into CR0).
15570 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15571 */
15572 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15573 {
15574 RTGCPTR GCPtrEffDst;
15575 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15576 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15577 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15578 if (fMemOperand)
15579 {
15580 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15581 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15582 }
15583 else
15584 GCPtrEffDst = NIL_RTGCPTR;
15585 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15586 break;
15587 }
15588
15589 default:
15590 {
15591 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15592 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15593 }
15594 }
15595
15596 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15597 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15598 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15599
15600 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15601 NOREF(pVM);
15602 return rcStrict;
15603}
15604
15605
15606/**
15607 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15608 * VM-exit.
15609 */
15610HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15611{
15612 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15613 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15614
15615 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15616 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15617 hmR0VmxReadExitQualVmcs(pVmxTransient);
15618 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15619 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15620 | CPUMCTX_EXTRN_EFER);
15621 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15622 AssertRCReturn(rc, rc);
15623
15624 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15625 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15626 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15627 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15628 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15629 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15630 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15631 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15632
15633 /*
15634 * Update exit history to see if this exit can be optimized.
15635 */
15636 VBOXSTRICTRC rcStrict;
15637 PCEMEXITREC pExitRec = NULL;
15638 if ( !fGstStepping
15639 && !fDbgStepping)
15640 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15641 !fIOString
15642 ? !fIOWrite
15643 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15644 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15645 : !fIOWrite
15646 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15647 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15648 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15649 if (!pExitRec)
15650 {
15651 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15652 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15653
15654 uint32_t const cbValue = s_aIOSizes[uIOSize];
15655 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15656 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15657 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15658 if (fIOString)
15659 {
15660 /*
15661 * INS/OUTS - I/O String instruction.
15662 *
15663 * Use instruction-information if available, otherwise fall back on
15664 * interpreting the instruction.
15665 */
15666 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15667 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15668 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15669 if (fInsOutsInfo)
15670 {
15671 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15672 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15673 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15674 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15675 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15676 if (fIOWrite)
15677 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15678 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15679 else
15680 {
15681 /*
15682 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15683 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15684 * See Intel Instruction spec. for "INS".
15685 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15686 */
15687 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15688 }
15689 }
15690 else
15691 rcStrict = IEMExecOne(pVCpu);
15692
15693 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15694 fUpdateRipAlready = true;
15695 }
15696 else
15697 {
15698 /*
15699 * IN/OUT - I/O instruction.
15700 */
15701 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15702 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15703 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15704 if (fIOWrite)
15705 {
15706 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15707 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15708 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15709 && !pCtx->eflags.Bits.u1TF)
15710 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15711 }
15712 else
15713 {
15714 uint32_t u32Result = 0;
15715 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15716 if (IOM_SUCCESS(rcStrict))
15717 {
15718 /* Save result of I/O IN instr. in AL/AX/EAX. */
15719 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15720 }
15721 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15722 && !pCtx->eflags.Bits.u1TF)
15723 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15724 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15725 }
15726 }
15727
15728 if (IOM_SUCCESS(rcStrict))
15729 {
15730 if (!fUpdateRipAlready)
15731 {
15732 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15733 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15734 }
15735
15736 /*
15737 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15738 * while booting Fedora 17 64-bit guest.
15739 *
15740 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15741 */
15742 if (fIOString)
15743 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15744
15745 /*
15746 * If any I/O breakpoints are armed, we need to check if one triggered
15747 * and take appropriate action.
15748 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15749 */
15750 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15751 AssertRCReturn(rc, rc);
15752
15753 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15754 * execution engines about whether hyper BPs and such are pending. */
15755 uint32_t const uDr7 = pCtx->dr[7];
15756 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15757 && X86_DR7_ANY_RW_IO(uDr7)
15758 && (pCtx->cr4 & X86_CR4_DE))
15759 || DBGFBpIsHwIoArmed(pVM)))
15760 {
15761 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15762
15763 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15764 VMMRZCallRing3Disable(pVCpu);
15765 HM_DISABLE_PREEMPT(pVCpu);
15766
15767 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15768
15769 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15770 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15771 {
15772 /* Raise #DB. */
15773 if (fIsGuestDbgActive)
15774 ASMSetDR6(pCtx->dr[6]);
15775 if (pCtx->dr[7] != uDr7)
15776 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15777
15778 hmR0VmxSetPendingXcptDB(pVCpu);
15779 }
15780 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15781 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15782 else if ( rcStrict2 != VINF_SUCCESS
15783 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15784 rcStrict = rcStrict2;
15785 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15786
15787 HM_RESTORE_PREEMPT();
15788 VMMRZCallRing3Enable(pVCpu);
15789 }
15790 }
15791
15792#ifdef VBOX_STRICT
15793 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15794 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15795 Assert(!fIOWrite);
15796 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15797 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15798 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15799 Assert(fIOWrite);
15800 else
15801 {
15802# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15803 * statuses, that the VMM device and some others may return. See
15804 * IOM_SUCCESS() for guidance. */
15805 AssertMsg( RT_FAILURE(rcStrict)
15806 || rcStrict == VINF_SUCCESS
15807 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15808 || rcStrict == VINF_EM_DBG_BREAKPOINT
15809 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15810 || rcStrict == VINF_EM_RAW_TO_R3
15811 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15812# endif
15813 }
15814#endif
15815 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15816 }
15817 else
15818 {
15819 /*
15820 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15821 */
15822 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15823 AssertRCReturn(rc2, rc2);
15824 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15825 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15826 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15827 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15828 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15829 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15830
15831 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15832 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15833
15834 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15835 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15836 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15837 }
15838 return rcStrict;
15839}
15840
15841
15842/**
15843 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15844 * VM-exit.
15845 */
15846HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15847{
15848 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15849
15850 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15851 hmR0VmxReadExitQualVmcs(pVmxTransient);
15852 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15853 {
15854 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15855 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15856 {
15857 uint32_t uErrCode;
15858 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15859 {
15860 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15861 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15862 }
15863 else
15864 uErrCode = 0;
15865
15866 RTGCUINTPTR GCPtrFaultAddress;
15867 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15868 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15869 else
15870 GCPtrFaultAddress = 0;
15871
15872 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15873
15874 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15875 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15876
15877 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15878 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15879 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15880 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15881 }
15882 }
15883
15884 /* Fall back to the interpreter to emulate the task-switch. */
15885 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15886 return VERR_EM_INTERPRETER;
15887}
15888
15889
15890/**
15891 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15892 */
15893HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15894{
15895 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15896
15897 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15898 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15899 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15900 AssertRC(rc);
15901 return VINF_EM_DBG_STEPPED;
15902}
15903
15904
15905/**
15906 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15907 */
15908HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15909{
15910 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15911 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15912
15913 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15914 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15915 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15916 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15917 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15918
15919 /*
15920 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15921 */
15922 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15923 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15924 {
15925 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15926 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15927 {
15928 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15929 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15930 }
15931 }
15932 else
15933 {
15934 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15935 return rcStrict;
15936 }
15937
15938 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15939 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15940 hmR0VmxReadExitQualVmcs(pVmxTransient);
15941 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15942 AssertRCReturn(rc, rc);
15943
15944 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15945 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15946 switch (uAccessType)
15947 {
15948 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15949 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15950 {
15951 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15952 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15953 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15954
15955 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15956 GCPhys &= PAGE_BASE_GC_MASK;
15957 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15958 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15959 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15960
15961 rcStrict = IOMR0MmioPhysHandler(pVCpu->CTX_SUFF(pVM), pVCpu,
15962 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW, GCPhys);
15963 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15964 if ( rcStrict == VINF_SUCCESS
15965 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15966 || rcStrict == VERR_PAGE_NOT_PRESENT)
15967 {
15968 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15969 | HM_CHANGED_GUEST_APIC_TPR);
15970 rcStrict = VINF_SUCCESS;
15971 }
15972 break;
15973 }
15974
15975 default:
15976 {
15977 Log4Func(("uAccessType=%#x\n", uAccessType));
15978 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15979 break;
15980 }
15981 }
15982
15983 if (rcStrict != VINF_SUCCESS)
15984 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15985 return rcStrict;
15986}
15987
15988
15989/**
15990 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15991 * VM-exit.
15992 */
15993HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15994{
15995 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15996 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15997
15998 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15999 if (!pVmxTransient->fIsNestedGuest)
16000 {
16001 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16002 if (pVmxTransient->fWasGuestDebugStateActive)
16003 {
16004 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16005 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16006 }
16007
16008 if ( !pVCpu->hm.s.fSingleInstruction
16009 && !pVmxTransient->fWasHyperDebugStateActive)
16010 {
16011 Assert(!DBGFIsStepping(pVCpu));
16012 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16013
16014 /* Don't intercept MOV DRx any more. */
16015 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16016 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16017 AssertRC(rc);
16018
16019 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16020 VMMRZCallRing3Disable(pVCpu);
16021 HM_DISABLE_PREEMPT(pVCpu);
16022
16023 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16024 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16025 Assert(CPUMIsGuestDebugStateActive(pVCpu));
16026
16027 HM_RESTORE_PREEMPT();
16028 VMMRZCallRing3Enable(pVCpu);
16029
16030#ifdef VBOX_WITH_STATISTICS
16031 hmR0VmxReadExitQualVmcs(pVmxTransient);
16032 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16033 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16034 else
16035 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16036#endif
16037 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16038 return VINF_SUCCESS;
16039 }
16040 }
16041
16042 /*
16043 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16044 * The EFER MSR is always up-to-date.
16045 * Update the segment registers and DR7 from the CPU.
16046 */
16047 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16048 hmR0VmxReadExitQualVmcs(pVmxTransient);
16049 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16050 AssertRCReturn(rc, rc);
16051 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16052
16053 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16054 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16055 {
16056 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16057 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16058 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16059 if (RT_SUCCESS(rc))
16060 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16061 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16062 }
16063 else
16064 {
16065 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16066 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16067 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16068 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16069 }
16070
16071 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16072 if (RT_SUCCESS(rc))
16073 {
16074 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16075 AssertRCReturn(rc2, rc2);
16076 return VINF_SUCCESS;
16077 }
16078 return rc;
16079}
16080
16081
16082/**
16083 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16084 * Conditional VM-exit.
16085 */
16086HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16087{
16088 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16089 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16090
16091 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16092 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16093 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16094 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16095 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16096
16097 /*
16098 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16099 */
16100 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16101 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16102 {
16103 /*
16104 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16105 * instruction emulation to inject the original event. Otherwise, injecting the original event
16106 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
16107 */
16108 if (!pVCpu->hm.s.Event.fPending)
16109 { /* likely */ }
16110 else
16111 {
16112 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16113#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16114 /** @todo NSTVMX: Think about how this should be handled. */
16115 if (pVmxTransient->fIsNestedGuest)
16116 return VERR_VMX_IPE_3;
16117#endif
16118 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16119 }
16120 }
16121 else
16122 {
16123 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16124 return rcStrict;
16125 }
16126
16127 /*
16128 * Get sufficient state and update the exit history entry.
16129 */
16130 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16131 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16132 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16133 AssertRCReturn(rc, rc);
16134
16135 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16136 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16137 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16138 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16139 if (!pExitRec)
16140 {
16141 /*
16142 * If we succeed, resume guest execution.
16143 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16144 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16145 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16146 * weird case. See @bugref{6043}.
16147 */
16148 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16149 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16150/** @todo bird: We can probably just go straight to IOM here and assume that
16151 * it's MMIO, then fall back on PGM if that hunch didn't work out so
16152 * well. However, we need to address that aliasing workarounds that
16153 * PGMR0Trap0eHandlerNPMisconfig implements. So, some care is needed.
16154 *
16155 * Might also be interesting to see if we can get this done more or
16156 * less locklessly inside IOM. Need to consider the lookup table
16157 * updating and use a bit more carefully first (or do all updates via
16158 * rendezvous) */
16159 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16160 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16161 if ( rcStrict == VINF_SUCCESS
16162 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16163 || rcStrict == VERR_PAGE_NOT_PRESENT)
16164 {
16165 /* Successfully handled MMIO operation. */
16166 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16167 | HM_CHANGED_GUEST_APIC_TPR);
16168 rcStrict = VINF_SUCCESS;
16169 }
16170 }
16171 else
16172 {
16173 /*
16174 * Frequent exit or something needing probing. Call EMHistoryExec.
16175 */
16176 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16177 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16178
16179 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16180 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16181
16182 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16183 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16184 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16185 }
16186 return rcStrict;
16187}
16188
16189
16190/**
16191 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16192 * VM-exit.
16193 */
16194HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16195{
16196 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16197 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16198
16199 hmR0VmxReadExitQualVmcs(pVmxTransient);
16200 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16201 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16202 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16203 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16204 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16205
16206 /*
16207 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16208 */
16209 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16210 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16211 {
16212 /*
16213 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16214 * we shall resolve the nested #PF and re-inject the original event.
16215 */
16216 if (pVCpu->hm.s.Event.fPending)
16217 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16218 }
16219 else
16220 {
16221 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16222 return rcStrict;
16223 }
16224
16225 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16226 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
16227 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16228 AssertRCReturn(rc, rc);
16229
16230 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16231 uint64_t const uExitQual = pVmxTransient->uExitQual;
16232 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16233
16234 RTGCUINT uErrorCode = 0;
16235 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16236 uErrorCode |= X86_TRAP_PF_ID;
16237 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16238 uErrorCode |= X86_TRAP_PF_RW;
16239 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16240 uErrorCode |= X86_TRAP_PF_P;
16241
16242 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16243 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16244 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16245
16246 /*
16247 * Handle the pagefault trap for the nested shadow table.
16248 */
16249 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16250 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16251 TRPMResetTrap(pVCpu);
16252
16253 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16254 if ( rcStrict == VINF_SUCCESS
16255 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16256 || rcStrict == VERR_PAGE_NOT_PRESENT)
16257 {
16258 /* Successfully synced our nested page tables. */
16259 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16260 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16261 return VINF_SUCCESS;
16262 }
16263
16264 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16265 return rcStrict;
16266}
16267
16268
16269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16270/**
16271 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16272 */
16273HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16274{
16275 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16276
16277 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16278 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16279 hmR0VmxReadExitQualVmcs(pVmxTransient);
16280 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16281 | CPUMCTX_EXTRN_HWVIRT
16282 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16283 AssertRCReturn(rc, rc);
16284
16285 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16286
16287 VMXVEXITINFO ExitInfo;
16288 RT_ZERO(ExitInfo);
16289 ExitInfo.uReason = pVmxTransient->uExitReason;
16290 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16291 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16292 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16293 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16294
16295 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16296 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16297 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16298 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16299 {
16300 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16301 rcStrict = VINF_SUCCESS;
16302 }
16303 return rcStrict;
16304}
16305
16306
16307/**
16308 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16309 */
16310HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16311{
16312 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16313
16314 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16315 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16316 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16317 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16318 AssertRCReturn(rc, rc);
16319
16320 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16321
16322 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16323 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
16324 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16325 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16326 {
16327 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16328 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16329 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16330 }
16331 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16332 return rcStrict;
16333}
16334
16335
16336/**
16337 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16338 */
16339HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16340{
16341 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16342
16343 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16344 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16345 hmR0VmxReadExitQualVmcs(pVmxTransient);
16346 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16347 | CPUMCTX_EXTRN_HWVIRT
16348 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16349 AssertRCReturn(rc, rc);
16350
16351 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16352
16353 VMXVEXITINFO ExitInfo;
16354 RT_ZERO(ExitInfo);
16355 ExitInfo.uReason = pVmxTransient->uExitReason;
16356 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16357 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16358 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16359 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16360
16361 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16362 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16363 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16364 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16365 {
16366 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16367 rcStrict = VINF_SUCCESS;
16368 }
16369 return rcStrict;
16370}
16371
16372
16373/**
16374 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16375 */
16376HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16377{
16378 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16379
16380 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16381 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16382 hmR0VmxReadExitQualVmcs(pVmxTransient);
16383 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16384 | CPUMCTX_EXTRN_HWVIRT
16385 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16386 AssertRCReturn(rc, rc);
16387
16388 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16389
16390 VMXVEXITINFO ExitInfo;
16391 RT_ZERO(ExitInfo);
16392 ExitInfo.uReason = pVmxTransient->uExitReason;
16393 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16394 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16395 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16396 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16397
16398 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16399 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16400 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16401 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16402 {
16403 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16404 rcStrict = VINF_SUCCESS;
16405 }
16406 return rcStrict;
16407}
16408
16409
16410/**
16411 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16412 */
16413HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16414{
16415 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16416
16417 /*
16418 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16419 * thus might not need to import the shadow VMCS state, it's safer just in case
16420 * code elsewhere dares look at unsynced VMCS fields.
16421 */
16422 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16423 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16424 hmR0VmxReadExitQualVmcs(pVmxTransient);
16425 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16426 | CPUMCTX_EXTRN_HWVIRT
16427 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16428 AssertRCReturn(rc, rc);
16429
16430 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16431
16432 VMXVEXITINFO ExitInfo;
16433 RT_ZERO(ExitInfo);
16434 ExitInfo.uReason = pVmxTransient->uExitReason;
16435 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16436 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16437 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16438 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16439 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16440
16441 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16442 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16443 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16444 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16445 {
16446 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16447 rcStrict = VINF_SUCCESS;
16448 }
16449 return rcStrict;
16450}
16451
16452
16453/**
16454 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16455 */
16456HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16457{
16458 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16459
16460 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16461 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16462 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16463 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16464 AssertRCReturn(rc, rc);
16465
16466 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16467
16468 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16469 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16470 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16471 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16472 {
16473 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16474 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16475 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16476 }
16477 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16478 return rcStrict;
16479}
16480
16481
16482/**
16483 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16484 */
16485HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16486{
16487 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16488
16489 /*
16490 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16491 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16492 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16493 */
16494 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16495 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16496 hmR0VmxReadExitQualVmcs(pVmxTransient);
16497 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16498 | CPUMCTX_EXTRN_HWVIRT
16499 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16500 AssertRCReturn(rc, rc);
16501
16502 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16503
16504 VMXVEXITINFO ExitInfo;
16505 RT_ZERO(ExitInfo);
16506 ExitInfo.uReason = pVmxTransient->uExitReason;
16507 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16508 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16509 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16510 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16511 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16512
16513 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16514 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16515 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16516 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16517 {
16518 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16519 rcStrict = VINF_SUCCESS;
16520 }
16521 return rcStrict;
16522}
16523
16524
16525/**
16526 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16527 */
16528HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16529{
16530 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16531
16532 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16533 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16534 | CPUMCTX_EXTRN_HWVIRT
16535 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16536 AssertRCReturn(rc, rc);
16537
16538 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16539
16540 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16541 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16542 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16543 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16544 {
16545 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16546 rcStrict = VINF_SUCCESS;
16547 }
16548 return rcStrict;
16549}
16550
16551
16552/**
16553 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16554 */
16555HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16556{
16557 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16558
16559 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16560 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16561 hmR0VmxReadExitQualVmcs(pVmxTransient);
16562 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16563 | CPUMCTX_EXTRN_HWVIRT
16564 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16565 AssertRCReturn(rc, rc);
16566
16567 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16568
16569 VMXVEXITINFO ExitInfo;
16570 RT_ZERO(ExitInfo);
16571 ExitInfo.uReason = pVmxTransient->uExitReason;
16572 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16573 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16574 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16575 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16576
16577 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16578 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16579 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16580 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16581 {
16582 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16583 rcStrict = VINF_SUCCESS;
16584 }
16585 return rcStrict;
16586}
16587
16588
16589/**
16590 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16591 */
16592HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16593{
16594 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16595
16596 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16597 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16598 hmR0VmxReadExitQualVmcs(pVmxTransient);
16599 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16600 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16601 AssertRCReturn(rc, rc);
16602
16603 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16604
16605 VMXVEXITINFO ExitInfo;
16606 RT_ZERO(ExitInfo);
16607 ExitInfo.uReason = pVmxTransient->uExitReason;
16608 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16609 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16610 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16611 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16612
16613 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16614 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16615 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16616 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16617 {
16618 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16619 rcStrict = VINF_SUCCESS;
16620 }
16621 return rcStrict;
16622}
16623#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16624/** @} */
16625
16626
16627#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16628/** @name Nested-guest VM-exit handlers.
16629 * @{
16630 */
16631/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16632/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16633/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16634
16635/**
16636 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16637 * Conditional VM-exit.
16638 */
16639HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16640{
16641 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16642
16643 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16644
16645 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16646 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16647 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16648
16649 switch (uExitIntType)
16650 {
16651 /*
16652 * Physical NMIs:
16653 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16654 */
16655 case VMX_EXIT_INT_INFO_TYPE_NMI:
16656 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16657
16658 /*
16659 * Hardware exceptions,
16660 * Software exceptions,
16661 * Privileged software exceptions:
16662 * Figure out if the exception must be delivered to the guest or the nested-guest.
16663 */
16664 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16665 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16666 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16667 {
16668 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16669 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16670 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16671 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16672
16673 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16674 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16675 pVmxTransient->uExitIntErrorCode);
16676 if (fIntercept)
16677 {
16678 /* Exit qualification is required for debug and page-fault exceptions. */
16679 hmR0VmxReadExitQualVmcs(pVmxTransient);
16680
16681 /*
16682 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16683 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16684 * length. However, if delivery of a software interrupt, software exception or privileged
16685 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16686 */
16687 VMXVEXITINFO ExitInfo;
16688 RT_ZERO(ExitInfo);
16689 ExitInfo.uReason = pVmxTransient->uExitReason;
16690 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16691 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16692
16693 VMXVEXITEVENTINFO ExitEventInfo;
16694 RT_ZERO(ExitEventInfo);
16695 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16696 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16697 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16698 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16699
16700#ifdef DEBUG_ramshankar
16701 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16702 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16703 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16704 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16705 {
16706 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16707 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16708 }
16709#endif
16710 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16711 }
16712
16713 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16714 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16715 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16716 }
16717
16718 /*
16719 * Software interrupts:
16720 * VM-exits cannot be caused by software interrupts.
16721 *
16722 * External interrupts:
16723 * This should only happen when "acknowledge external interrupts on VM-exit"
16724 * control is set. However, we never set this when executing a guest or
16725 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16726 * the guest.
16727 */
16728 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16729 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16730 default:
16731 {
16732 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16733 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16734 }
16735 }
16736}
16737
16738
16739/**
16740 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16741 * Unconditional VM-exit.
16742 */
16743HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16744{
16745 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16746 return IEMExecVmxVmexitTripleFault(pVCpu);
16747}
16748
16749
16750/**
16751 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16752 */
16753HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16754{
16755 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16756
16757 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16758 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16759 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16760}
16761
16762
16763/**
16764 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16765 */
16766HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16767{
16768 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16769
16770 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16771 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16772 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16773}
16774
16775
16776/**
16777 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16778 * Unconditional VM-exit.
16779 */
16780HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16781{
16782 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16783
16784 hmR0VmxReadExitQualVmcs(pVmxTransient);
16785 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16786 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16787 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16788
16789 VMXVEXITINFO ExitInfo;
16790 RT_ZERO(ExitInfo);
16791 ExitInfo.uReason = pVmxTransient->uExitReason;
16792 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16793 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16794
16795 VMXVEXITEVENTINFO ExitEventInfo;
16796 RT_ZERO(ExitEventInfo);
16797 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16798 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16799 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16800}
16801
16802
16803/**
16804 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16805 */
16806HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16807{
16808 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16809
16810 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16811 {
16812 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16813 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16814 }
16815 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16816}
16817
16818
16819/**
16820 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16821 */
16822HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16823{
16824 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16825
16826 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16827 {
16828 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16829 hmR0VmxReadExitQualVmcs(pVmxTransient);
16830
16831 VMXVEXITINFO ExitInfo;
16832 RT_ZERO(ExitInfo);
16833 ExitInfo.uReason = pVmxTransient->uExitReason;
16834 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16835 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16836 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16837 }
16838 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16839}
16840
16841
16842/**
16843 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16844 */
16845HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16846{
16847 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16848
16849 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16850 {
16851 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16852 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16853 }
16854 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16855}
16856
16857
16858/**
16859 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16860 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16861 */
16862HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16863{
16864 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16865
16866 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16867 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16868
16869 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16870
16871 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16872 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16873 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16874
16875 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16876 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16877 u64VmcsField &= UINT64_C(0xffffffff);
16878
16879 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16880 {
16881 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16882 hmR0VmxReadExitQualVmcs(pVmxTransient);
16883
16884 VMXVEXITINFO ExitInfo;
16885 RT_ZERO(ExitInfo);
16886 ExitInfo.uReason = pVmxTransient->uExitReason;
16887 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16888 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16889 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16890 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16891 }
16892
16893 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16894 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16895 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16896}
16897
16898
16899/**
16900 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16901 */
16902HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16903{
16904 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16905
16906 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16907 {
16908 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16909 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16910 }
16911
16912 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16913}
16914
16915
16916/**
16917 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16918 * Conditional VM-exit.
16919 */
16920HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16921{
16922 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16923
16924 hmR0VmxReadExitQualVmcs(pVmxTransient);
16925 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16926
16927 VBOXSTRICTRC rcStrict;
16928 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16929 switch (uAccessType)
16930 {
16931 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16932 {
16933 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16934 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16935 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16936 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16937
16938 bool fIntercept;
16939 switch (iCrReg)
16940 {
16941 case 0:
16942 case 4:
16943 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(&pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16944 break;
16945
16946 case 3:
16947 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16948 break;
16949
16950 case 8:
16951 fIntercept = CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16952 break;
16953
16954 default:
16955 fIntercept = false;
16956 break;
16957 }
16958 if (fIntercept)
16959 {
16960 VMXVEXITINFO ExitInfo;
16961 RT_ZERO(ExitInfo);
16962 ExitInfo.uReason = pVmxTransient->uExitReason;
16963 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16964 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16965 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16966 }
16967 else
16968 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16969 break;
16970 }
16971
16972 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16973 {
16974 /*
16975 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16976 * CR2 reads do not cause a VM-exit.
16977 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16978 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16979 */
16980 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16981 if ( iCrReg == 3
16982 || iCrReg == 8)
16983 {
16984 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16985 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16986 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16987 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, uIntercept))
16988 {
16989 VMXVEXITINFO ExitInfo;
16990 RT_ZERO(ExitInfo);
16991 ExitInfo.uReason = pVmxTransient->uExitReason;
16992 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16993 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16994 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16995 }
16996 else
16997 {
16998 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16999 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
17000 }
17001 }
17002 else
17003 {
17004 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17005 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17006 }
17007 break;
17008 }
17009
17010 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17011 {
17012 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17013 Assert(pVmcsNstGst);
17014 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17015 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17016 if ( (uGstHostMask & X86_CR0_TS)
17017 && (uReadShadow & X86_CR0_TS))
17018 {
17019 VMXVEXITINFO ExitInfo;
17020 RT_ZERO(ExitInfo);
17021 ExitInfo.uReason = pVmxTransient->uExitReason;
17022 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17023 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17024 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17025 }
17026 else
17027 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
17028 break;
17029 }
17030
17031 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17032 {
17033 RTGCPTR GCPtrEffDst;
17034 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17035 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17036 if (fMemOperand)
17037 {
17038 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17039 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17040 }
17041 else
17042 GCPtrEffDst = NIL_RTGCPTR;
17043
17044 if (CPUMIsGuestVmxLmswInterceptSet(&pVCpu->cpum.GstCtx, uNewMsw))
17045 {
17046 VMXVEXITINFO ExitInfo;
17047 RT_ZERO(ExitInfo);
17048 ExitInfo.uReason = pVmxTransient->uExitReason;
17049 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17050 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17051 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17052 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17053 }
17054 else
17055 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
17056 break;
17057 }
17058
17059 default:
17060 {
17061 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17062 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17063 }
17064 }
17065
17066 if (rcStrict == VINF_IEM_RAISED_XCPT)
17067 {
17068 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17069 rcStrict = VINF_SUCCESS;
17070 }
17071 return rcStrict;
17072}
17073
17074
17075/**
17076 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17077 * Conditional VM-exit.
17078 */
17079HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17080{
17081 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17082
17083 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17084 {
17085 hmR0VmxReadExitQualVmcs(pVmxTransient);
17086 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17087
17088 VMXVEXITINFO ExitInfo;
17089 RT_ZERO(ExitInfo);
17090 ExitInfo.uReason = pVmxTransient->uExitReason;
17091 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17092 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17093 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17094 }
17095 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17096}
17097
17098
17099/**
17100 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17101 * Conditional VM-exit.
17102 */
17103HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17104{
17105 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17106
17107 hmR0VmxReadExitQualVmcs(pVmxTransient);
17108
17109 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17110 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17111 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17112
17113 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17114 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17115 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17116 {
17117 /*
17118 * IN/OUT instruction:
17119 * - Provides VM-exit instruction length.
17120 *
17121 * INS/OUTS instruction:
17122 * - Provides VM-exit instruction length.
17123 * - Provides Guest-linear address.
17124 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17125 */
17126 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
17127 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17128
17129 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17130 pVmxTransient->ExitInstrInfo.u = 0;
17131 pVmxTransient->uGuestLinearAddr = 0;
17132
17133 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17134 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17135 if (fIOString)
17136 {
17137 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
17138 if (fVmxInsOutsInfo)
17139 {
17140 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17141 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17142 }
17143 }
17144
17145 VMXVEXITINFO ExitInfo;
17146 RT_ZERO(ExitInfo);
17147 ExitInfo.uReason = pVmxTransient->uExitReason;
17148 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17149 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17150 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17151 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17152 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17153 }
17154 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17155}
17156
17157
17158/**
17159 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17160 */
17161HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17162{
17163 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17164
17165 uint32_t fMsrpm;
17166 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17167 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17168 else
17169 fMsrpm = VMXMSRPM_EXIT_RD;
17170
17171 if (fMsrpm & VMXMSRPM_EXIT_RD)
17172 {
17173 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17174 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17175 }
17176 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17177}
17178
17179
17180/**
17181 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17182 */
17183HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17184{
17185 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17186
17187 uint32_t fMsrpm;
17188 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17189 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17190 else
17191 fMsrpm = VMXMSRPM_EXIT_WR;
17192
17193 if (fMsrpm & VMXMSRPM_EXIT_WR)
17194 {
17195 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17196 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17197 }
17198 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17199}
17200
17201
17202/**
17203 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17204 */
17205HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17206{
17207 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17208
17209 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17210 {
17211 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17212 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17213 }
17214 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17215}
17216
17217
17218/**
17219 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17220 * VM-exit.
17221 */
17222HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17223{
17224 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17225
17226 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17227 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17228 VMXVEXITINFO ExitInfo;
17229 RT_ZERO(ExitInfo);
17230 ExitInfo.uReason = pVmxTransient->uExitReason;
17231 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17232 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17233}
17234
17235
17236/**
17237 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17238 */
17239HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17240{
17241 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17242
17243 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17244 {
17245 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17246 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17247 }
17248 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17249}
17250
17251
17252/**
17253 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17254 */
17255HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17256{
17257 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17258
17259 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17260 * PAUSE when executing a nested-guest? If it does not, we would not need
17261 * to check for the intercepts here. Just call VM-exit... */
17262
17263 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17264 if ( CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17265 || CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17266 {
17267 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17268 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17269 }
17270 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17271}
17272
17273
17274/**
17275 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17276 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17277 */
17278HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17279{
17280 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17281
17282 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17283 {
17284 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
17285 VMXVEXITINFO ExitInfo;
17286 RT_ZERO(ExitInfo);
17287 ExitInfo.uReason = pVmxTransient->uExitReason;
17288 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
17289 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
17290 }
17291 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17292}
17293
17294
17295/**
17296 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17297 * VM-exit.
17298 */
17299HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17300{
17301 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17302
17303 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17304 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17305 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17306 hmR0VmxReadExitQualVmcs(pVmxTransient);
17307
17308 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17309
17310 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
17311 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
17312
17313 VMXVEXITINFO ExitInfo;
17314 RT_ZERO(ExitInfo);
17315 ExitInfo.uReason = pVmxTransient->uExitReason;
17316 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17317 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17318
17319 VMXVEXITEVENTINFO ExitEventInfo;
17320 RT_ZERO(ExitEventInfo);
17321 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17322 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17323 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17324}
17325
17326
17327/**
17328 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17329 * Conditional VM-exit.
17330 */
17331HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17332{
17333 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17334
17335 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17336 hmR0VmxReadExitQualVmcs(pVmxTransient);
17337 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17338}
17339
17340
17341/**
17342 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17343 * Conditional VM-exit.
17344 */
17345HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17346{
17347 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17348
17349 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17350 hmR0VmxReadExitQualVmcs(pVmxTransient);
17351 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17352}
17353
17354
17355/**
17356 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17357 */
17358HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17359{
17360 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17361
17362 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17363 {
17364 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17365 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17366 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17367 }
17368 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17369}
17370
17371
17372/**
17373 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17374 */
17375HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17376{
17377 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17378
17379 if (CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17380 {
17381 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17382 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17383 }
17384 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17385}
17386
17387
17388/**
17389 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17390 */
17391HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17392{
17393 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17394
17395 if (CPUMIsGuestVmxProcCtlsSet(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17396 {
17397 Assert(CPUMIsGuestVmxProcCtls2Set(&pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17398 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17399 hmR0VmxReadExitQualVmcs(pVmxTransient);
17400 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17401
17402 VMXVEXITINFO ExitInfo;
17403 RT_ZERO(ExitInfo);
17404 ExitInfo.uReason = pVmxTransient->uExitReason;
17405 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17406 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17407 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17408 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17409 }
17410 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17411}
17412
17413
17414/**
17415 * Nested-guest VM-exit handler for invalid-guest state
17416 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17417 */
17418HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17419{
17420 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17421
17422 /*
17423 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17424 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17425 * Handle it like it's in an invalid guest state of the outer guest.
17426 *
17427 * When the fast path is implemented, this should be changed to cause the corresponding
17428 * nested-guest VM-exit.
17429 */
17430 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17431}
17432
17433
17434/**
17435 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17436 * and only provide the instruction length.
17437 *
17438 * Unconditional VM-exit.
17439 */
17440HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17441{
17442 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17443
17444#ifdef VBOX_STRICT
17445 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17446 switch (pVmxTransient->uExitReason)
17447 {
17448 case VMX_EXIT_ENCLS:
17449 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17450 break;
17451
17452 case VMX_EXIT_VMFUNC:
17453 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_VMFUNC));
17454 break;
17455 }
17456#endif
17457
17458 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17459 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17460}
17461
17462
17463/**
17464 * Nested-guest VM-exit handler for instructions that provide instruction length as
17465 * well as more information.
17466 *
17467 * Unconditional VM-exit.
17468 */
17469HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17470{
17471 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17472
17473#ifdef VBOX_STRICT
17474 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17475 switch (pVmxTransient->uExitReason)
17476 {
17477 case VMX_EXIT_GDTR_IDTR_ACCESS:
17478 case VMX_EXIT_LDTR_TR_ACCESS:
17479 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17480 break;
17481
17482 case VMX_EXIT_RDRAND:
17483 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17484 break;
17485
17486 case VMX_EXIT_RDSEED:
17487 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17488 break;
17489
17490 case VMX_EXIT_XSAVES:
17491 case VMX_EXIT_XRSTORS:
17492 /** @todo NSTVMX: Verify XSS-bitmap. */
17493 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17494 break;
17495
17496 case VMX_EXIT_UMWAIT:
17497 case VMX_EXIT_TPAUSE:
17498 Assert(CPUMIsGuestVmxProcCtlsSet(pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17499 Assert(CPUMIsGuestVmxProcCtls2Set(pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17500 break;
17501 }
17502#endif
17503
17504 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17505 hmR0VmxReadExitQualVmcs(pVmxTransient);
17506 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17507
17508 VMXVEXITINFO ExitInfo;
17509 RT_ZERO(ExitInfo);
17510 ExitInfo.uReason = pVmxTransient->uExitReason;
17511 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17512 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17513 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17514 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17515}
17516
17517/** @} */
17518#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17519
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