VirtualBox

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

Last change on this file since 80014 was 79992, checked in by vboxsync, 6 years ago

VMM/HMVMXR0: Nested VMX: bugref:9180 fVirtApicPageDirty not used anymore, slated for removal.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 737.4 KB
Line 
1/* $Id: HMVMXR0.cpp 79992 2019-07-26 05:53:34Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/selm.h>
35#include <VBox/vmm/tm.h>
36#include <VBox/vmm/em.h>
37#include <VBox/vmm/gim.h>
38#include <VBox/vmm/apic.h>
39#ifdef VBOX_WITH_REM
40# include <VBox/vmm/rem.h>
41#endif
42#include "HMInternal.h"
43#include <VBox/vmm/vm.h>
44#include <VBox/vmm/hmvmxinline.h>
45#include "HMVMXR0.h"
46#include "dtrace/VBoxVMM.h"
47
48#ifdef DEBUG_ramshankar
49# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
50# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
51# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
52# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
53# define HMVMX_ALWAYS_CLEAN_TRANSIENT
54# define HMVMX_ALWAYS_CHECK_GUEST_STATE
55# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
56# define HMVMX_ALWAYS_TRAP_PF
57# define HMVMX_ALWAYS_FLUSH_TLB
58# define HMVMX_ALWAYS_SWAP_EFER
59#endif
60
61
62/*********************************************************************************************************************************
63* Defined Constants And Macros *
64*********************************************************************************************************************************/
65/** Use the function table. */
66#define HMVMX_USE_FUNCTION_TABLE
67
68/** Determine which tagged-TLB flush handler to use. */
69#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
70#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
71#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
72#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
73
74/**
75 * Flags to skip redundant reads of some common VMCS fields that are not part of
76 * the guest-CPU or VCPU state but are needed while handling VM-exits.
77 */
78#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
79#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
80#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
81#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
82#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
83#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
84#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
85#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
86#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
87
88/** All the VMCS fields required for processing of exception/NMI VM-exits. */
89#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
90 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
91 | HMVMX_READ_EXIT_INSTR_LEN \
92 | HMVMX_READ_IDT_VECTORING_INFO \
93 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
94
95/** Assert that all the given fields have been read from the VMCS. */
96#ifdef VBOX_STRICT
97# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
98 do { \
99 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
100 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
101 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
102 } while (0)
103#else
104# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
105#endif
106
107/**
108 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
109 * guest using hardware-assisted VMX.
110 *
111 * This excludes state like GPRs (other than RSP) which are always are
112 * swapped and restored across the world-switch and also registers like EFER,
113 * MSR which cannot be modified by the guest without causing a VM-exit.
114 */
115#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
116 | CPUMCTX_EXTRN_RFLAGS \
117 | CPUMCTX_EXTRN_RSP \
118 | CPUMCTX_EXTRN_SREG_MASK \
119 | CPUMCTX_EXTRN_TABLE_MASK \
120 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
121 | CPUMCTX_EXTRN_SYSCALL_MSRS \
122 | CPUMCTX_EXTRN_SYSENTER_MSRS \
123 | CPUMCTX_EXTRN_TSC_AUX \
124 | CPUMCTX_EXTRN_OTHER_MSRS \
125 | CPUMCTX_EXTRN_CR0 \
126 | CPUMCTX_EXTRN_CR3 \
127 | CPUMCTX_EXTRN_CR4 \
128 | CPUMCTX_EXTRN_DR7 \
129 | CPUMCTX_EXTRN_HWVIRT \
130 | CPUMCTX_EXTRN_HM_VMX_MASK)
131
132/**
133 * Exception bitmap mask for real-mode guests (real-on-v86).
134 *
135 * We need to intercept all exceptions manually except:
136 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
137 * due to bugs in Intel CPUs.
138 * - \#PF need not be intercepted even in real-mode if we have nested paging
139 * support.
140 */
141#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
142 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
143 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
144 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
145 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
146 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
147 | RT_BIT(X86_XCPT_XF))
148
149/** Maximum VM-instruction error number. */
150#define HMVMX_INSTR_ERROR_MAX 28
151
152/** Profiling macro. */
153#ifdef HM_PROFILE_EXIT_DISPATCH
154# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
155# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
156#else
157# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
158# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
159#endif
160
161/** Assert that preemption is disabled or covered by thread-context hooks. */
162#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
163 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
164
165/** Assert that we haven't migrated CPUs when thread-context hooks are not
166 * used. */
167#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
168 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
169 ("Illegal migration! Entered on CPU %u Current %u\n", \
170 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
171
172/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
173 * context. */
174#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
175 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
176 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
177
178/** Log the VM-exit reason with an easily visible marker to identify it in a
179 * potential sea of logging data. */
180#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
181 do { \
182 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, \
183 HMGetVmxExitName(a_uExitReason))); \
184 } while (0) \
185
186
187/*********************************************************************************************************************************
188* Structures and Typedefs *
189*********************************************************************************************************************************/
190/**
191 * VMX per-VCPU transient state.
192 *
193 * A state structure for holding miscellaneous information across
194 * VMX non-root operation and restored after the transition.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** The host's rflags/eflags. */
199 RTCCUINTREG fEFlags;
200#if HC_ARCH_BITS == 32
201 uint32_t u32Alignment0;
202#endif
203 /** The guest's TPR value used for TPR shadowing. */
204 uint8_t u8GuestTpr;
205 /** Alignment. */
206 uint8_t abAlignment0[7];
207
208 /** The basic VM-exit reason. */
209 uint16_t uExitReason;
210 /** Alignment. */
211 uint16_t u16Alignment0;
212 /** The VM-exit interruption error code. */
213 uint32_t uExitIntErrorCode;
214 /** The VM-exit exit code qualification. */
215 uint64_t uExitQual;
216 /** The Guest-linear address. */
217 uint64_t uGuestLinearAddr;
218 /** The Guest-physical address. */
219 uint64_t uGuestPhysicalAddr;
220
221 /** The VM-exit interruption-information field. */
222 uint32_t uExitIntInfo;
223 /** The VM-exit instruction-length field. */
224 uint32_t cbInstr;
225 /** The VM-exit instruction-information field. */
226 VMXEXITINSTRINFO ExitInstrInfo;
227 /** Whether the VM-entry failed or not. */
228 bool fVMEntryFailed;
229 /** Whether we are currently executing a nested-guest. */
230 bool fIsNestedGuest;
231 /** Alignment. */
232 uint8_t abAlignment1[2];
233
234 /** The VM-entry interruption-information field. */
235 uint32_t uEntryIntInfo;
236 /** The VM-entry exception error code field. */
237 uint32_t uEntryXcptErrorCode;
238 /** The VM-entry instruction length field. */
239 uint32_t cbEntryInstr;
240
241 /** IDT-vectoring information field. */
242 uint32_t uIdtVectoringInfo;
243 /** IDT-vectoring error code. */
244 uint32_t uIdtVectoringErrorCode;
245
246 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
247 uint32_t fVmcsFieldsRead;
248
249 /** Whether the guest debug state was active at the time of VM-exit. */
250 bool fWasGuestDebugStateActive;
251 /** Whether the hyper debug state was active at the time of VM-exit. */
252 bool fWasHyperDebugStateActive;
253 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
254 bool fUpdatedTscOffsettingAndPreemptTimer;
255 /** Whether the VM-exit was caused by a page-fault during delivery of a
256 * contributory exception or a page-fault. */
257 bool fVectoringDoublePF;
258 /** Whether the VM-exit was caused by a page-fault during delivery of an
259 * external interrupt or NMI. */
260 bool fVectoringPF;
261 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
262 * area after VM-exit. */
263 bool fRemoveTscAuxMsr;
264 bool afAlignment0[2];
265
266 /** The VMCS info. object. */
267 PVMXVMCSINFO pVmcsInfo;
268} VMXTRANSIENT;
269AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
271AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
272AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
273AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
274AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
275/** Pointer to VMX transient state. */
276typedef VMXTRANSIENT *PVMXTRANSIENT;
277/** Pointer to a const VMX transient state. */
278typedef const VMXTRANSIENT *PCVMXTRANSIENT;
279
280/**
281 * Memory operand read or write access.
282 */
283typedef enum VMXMEMACCESS
284{
285 VMXMEMACCESS_READ = 0,
286 VMXMEMACCESS_WRITE = 1
287} VMXMEMACCESS;
288
289/**
290 * VMX VM-exit handler.
291 *
292 * @returns Strict VBox status code (i.e. informational status codes too).
293 * @param pVCpu The cross context virtual CPU structure.
294 * @param pVmxTransient The VMX-transient structure.
295 */
296#ifndef HMVMX_USE_FUNCTION_TABLE
297typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
298#else
299typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
300/** Pointer to VM-exit handler. */
301typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
302#endif
303
304/**
305 * VMX VM-exit handler, non-strict status code.
306 *
307 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
308 *
309 * @returns VBox status code, no informational status code returned.
310 * @param pVCpu The cross context virtual CPU structure.
311 * @param pVmxTransient The VMX-transient structure.
312 *
313 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
314 * use of that status code will be replaced with VINF_EM_SOMETHING
315 * later when switching over to IEM.
316 */
317#ifndef HMVMX_USE_FUNCTION_TABLE
318typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
319#else
320typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
321#endif
322
323
324/*********************************************************************************************************************************
325* Internal Functions *
326*********************************************************************************************************************************/
327#ifndef HMVMX_USE_FUNCTION_TABLE
328DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
329# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
330# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
331#else
332# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
333# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
334#endif
335#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
336DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
337#endif
338
339static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
340#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
341static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
342#endif
343
344/** @name VM-exit handler prototypes.
345 * @{
346 */
347static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
348static FNVMXEXITHANDLER hmR0VmxExitExtInt;
349static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
350static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
351static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
352static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
353static FNVMXEXITHANDLER hmR0VmxExitCpuid;
354static FNVMXEXITHANDLER hmR0VmxExitGetsec;
355static FNVMXEXITHANDLER hmR0VmxExitHlt;
356static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
357static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
358static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
359static FNVMXEXITHANDLER hmR0VmxExitVmcall;
360#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
361static FNVMXEXITHANDLER hmR0VmxExitVmclear;
362static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
363static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
364static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
365static FNVMXEXITHANDLER hmR0VmxExitVmread;
366static FNVMXEXITHANDLER hmR0VmxExitVmresume;
367static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
368static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
369static FNVMXEXITHANDLER hmR0VmxExitVmxon;
370static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
371#endif
372static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
373static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
374static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
375static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
376static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
377static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
378static FNVMXEXITHANDLER hmR0VmxExitMwait;
379static FNVMXEXITHANDLER hmR0VmxExitMtf;
380static FNVMXEXITHANDLER hmR0VmxExitMonitor;
381static FNVMXEXITHANDLER hmR0VmxExitPause;
382static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
383static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
384static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
385static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
386static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
387static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
389static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
390static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
391static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
392static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
393static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
394/** @} */
395
396#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
397/** @name Nested-guest VM-exit handler prototypes.
398 * @{
399 */
400static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
401static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
402static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
403static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
404static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
405static FNVMXEXITHANDLER hmR0VmxExitHltNested;
406static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
407static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
408static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
409static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
410static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
411static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
412static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
413static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
414static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
415static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
416static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
417static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
418static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
419static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
420static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
421static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
422static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
423static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
424static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
425static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
426static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
427static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
428static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
429/** @} */
430#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
431
432
433/*********************************************************************************************************************************
434* Global Variables *
435*********************************************************************************************************************************/
436#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
437/**
438 * Array of all VMCS fields.
439 * Any fields added to the VT-x spec. should be added here.
440 *
441 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
442 * of nested-guests.
443 */
444static const uint32_t g_aVmcsFields[] =
445{
446 /* 16-bit control fields. */
447 VMX_VMCS16_VPID,
448 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
449 VMX_VMCS16_EPTP_INDEX,
450
451 /* 16-bit guest-state fields. */
452 VMX_VMCS16_GUEST_ES_SEL,
453 VMX_VMCS16_GUEST_CS_SEL,
454 VMX_VMCS16_GUEST_SS_SEL,
455 VMX_VMCS16_GUEST_DS_SEL,
456 VMX_VMCS16_GUEST_FS_SEL,
457 VMX_VMCS16_GUEST_GS_SEL,
458 VMX_VMCS16_GUEST_LDTR_SEL,
459 VMX_VMCS16_GUEST_TR_SEL,
460 VMX_VMCS16_GUEST_INTR_STATUS,
461 VMX_VMCS16_GUEST_PML_INDEX,
462
463 /* 16-bits host-state fields. */
464 VMX_VMCS16_HOST_ES_SEL,
465 VMX_VMCS16_HOST_CS_SEL,
466 VMX_VMCS16_HOST_SS_SEL,
467 VMX_VMCS16_HOST_DS_SEL,
468 VMX_VMCS16_HOST_FS_SEL,
469 VMX_VMCS16_HOST_GS_SEL,
470 VMX_VMCS16_HOST_TR_SEL,
471
472 /* 64-bit control fields. */
473 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
474 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
475 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
476 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
477 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
478 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
479 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
480 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
481 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
482 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
483 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
484 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
485 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
486 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
487 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
488 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
489 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
490 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
491 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
492 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
493 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
494 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
495 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
496 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
497 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
498 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
499 VMX_VMCS64_CTRL_EPTP_FULL,
500 VMX_VMCS64_CTRL_EPTP_HIGH,
501 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
502 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
503 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
504 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
505 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
506 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
507 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
508 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
509 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
510 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
511 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
512 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
513 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
514 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
515 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
516 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
517 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
518 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
519 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
520 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
521 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
522 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
523
524 /* 64-bit read-only data fields. */
525 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
526 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
527
528 /* 64-bit guest-state fields. */
529 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
530 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
531 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
532 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
533 VMX_VMCS64_GUEST_PAT_FULL,
534 VMX_VMCS64_GUEST_PAT_HIGH,
535 VMX_VMCS64_GUEST_EFER_FULL,
536 VMX_VMCS64_GUEST_EFER_HIGH,
537 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
538 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
539 VMX_VMCS64_GUEST_PDPTE0_FULL,
540 VMX_VMCS64_GUEST_PDPTE0_HIGH,
541 VMX_VMCS64_GUEST_PDPTE1_FULL,
542 VMX_VMCS64_GUEST_PDPTE1_HIGH,
543 VMX_VMCS64_GUEST_PDPTE2_FULL,
544 VMX_VMCS64_GUEST_PDPTE2_HIGH,
545 VMX_VMCS64_GUEST_PDPTE3_FULL,
546 VMX_VMCS64_GUEST_PDPTE3_HIGH,
547 VMX_VMCS64_GUEST_BNDCFGS_FULL,
548 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
549
550 /* 64-bit host-state fields. */
551 VMX_VMCS64_HOST_PAT_FULL,
552 VMX_VMCS64_HOST_PAT_HIGH,
553 VMX_VMCS64_HOST_EFER_FULL,
554 VMX_VMCS64_HOST_EFER_HIGH,
555 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
556 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
557
558 /* 32-bit control fields. */
559 VMX_VMCS32_CTRL_PIN_EXEC,
560 VMX_VMCS32_CTRL_PROC_EXEC,
561 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
562 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
563 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
564 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
565 VMX_VMCS32_CTRL_EXIT,
566 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
567 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
568 VMX_VMCS32_CTRL_ENTRY,
569 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
570 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
571 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
572 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
573 VMX_VMCS32_CTRL_TPR_THRESHOLD,
574 VMX_VMCS32_CTRL_PROC_EXEC2,
575 VMX_VMCS32_CTRL_PLE_GAP,
576 VMX_VMCS32_CTRL_PLE_WINDOW,
577
578 /* 32-bits read-only fields. */
579 VMX_VMCS32_RO_VM_INSTR_ERROR,
580 VMX_VMCS32_RO_EXIT_REASON,
581 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
582 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
583 VMX_VMCS32_RO_IDT_VECTORING_INFO,
584 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
585 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
586 VMX_VMCS32_RO_EXIT_INSTR_INFO,
587
588 /* 32-bit guest-state fields. */
589 VMX_VMCS32_GUEST_ES_LIMIT,
590 VMX_VMCS32_GUEST_CS_LIMIT,
591 VMX_VMCS32_GUEST_SS_LIMIT,
592 VMX_VMCS32_GUEST_DS_LIMIT,
593 VMX_VMCS32_GUEST_FS_LIMIT,
594 VMX_VMCS32_GUEST_GS_LIMIT,
595 VMX_VMCS32_GUEST_LDTR_LIMIT,
596 VMX_VMCS32_GUEST_TR_LIMIT,
597 VMX_VMCS32_GUEST_GDTR_LIMIT,
598 VMX_VMCS32_GUEST_IDTR_LIMIT,
599 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
602 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
603 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
604 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
605 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
606 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
607 VMX_VMCS32_GUEST_INT_STATE,
608 VMX_VMCS32_GUEST_ACTIVITY_STATE,
609 VMX_VMCS32_GUEST_SMBASE,
610 VMX_VMCS32_GUEST_SYSENTER_CS,
611 VMX_VMCS32_PREEMPT_TIMER_VALUE,
612
613 /* 32-bit host-state fields. */
614 VMX_VMCS32_HOST_SYSENTER_CS,
615
616 /* Natural-width control fields. */
617 VMX_VMCS_CTRL_CR0_MASK,
618 VMX_VMCS_CTRL_CR4_MASK,
619 VMX_VMCS_CTRL_CR0_READ_SHADOW,
620 VMX_VMCS_CTRL_CR4_READ_SHADOW,
621 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
622 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
623 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
624 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
625
626 /* Natural-width read-only data fields. */
627 VMX_VMCS_RO_EXIT_QUALIFICATION,
628 VMX_VMCS_RO_IO_RCX,
629 VMX_VMCS_RO_IO_RSI,
630 VMX_VMCS_RO_IO_RDI,
631 VMX_VMCS_RO_IO_RIP,
632 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
633
634 /* Natural-width guest-state field */
635 VMX_VMCS_GUEST_CR0,
636 VMX_VMCS_GUEST_CR3,
637 VMX_VMCS_GUEST_CR4,
638 VMX_VMCS_GUEST_ES_BASE,
639 VMX_VMCS_GUEST_CS_BASE,
640 VMX_VMCS_GUEST_SS_BASE,
641 VMX_VMCS_GUEST_DS_BASE,
642 VMX_VMCS_GUEST_FS_BASE,
643 VMX_VMCS_GUEST_GS_BASE,
644 VMX_VMCS_GUEST_LDTR_BASE,
645 VMX_VMCS_GUEST_TR_BASE,
646 VMX_VMCS_GUEST_GDTR_BASE,
647 VMX_VMCS_GUEST_IDTR_BASE,
648 VMX_VMCS_GUEST_DR7,
649 VMX_VMCS_GUEST_RSP,
650 VMX_VMCS_GUEST_RIP,
651 VMX_VMCS_GUEST_RFLAGS,
652 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
653 VMX_VMCS_GUEST_SYSENTER_ESP,
654 VMX_VMCS_GUEST_SYSENTER_EIP,
655
656 /* Natural-width host-state fields */
657 VMX_VMCS_HOST_CR0,
658 VMX_VMCS_HOST_CR3,
659 VMX_VMCS_HOST_CR4,
660 VMX_VMCS_HOST_FS_BASE,
661 VMX_VMCS_HOST_GS_BASE,
662 VMX_VMCS_HOST_TR_BASE,
663 VMX_VMCS_HOST_GDTR_BASE,
664 VMX_VMCS_HOST_IDTR_BASE,
665 VMX_VMCS_HOST_SYSENTER_ESP,
666 VMX_VMCS_HOST_SYSENTER_EIP,
667 VMX_VMCS_HOST_RSP,
668 VMX_VMCS_HOST_RIP
669};
670#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
671
672#ifdef VMX_USE_CACHED_VMCS_ACCESSES
673static const uint32_t g_aVmcsCacheSegBase[] =
674{
675 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
676 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
677 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
678 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
679 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
680 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
681};
682AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
683#endif
684static const uint32_t g_aVmcsSegBase[] =
685{
686 VMX_VMCS_GUEST_ES_BASE,
687 VMX_VMCS_GUEST_CS_BASE,
688 VMX_VMCS_GUEST_SS_BASE,
689 VMX_VMCS_GUEST_DS_BASE,
690 VMX_VMCS_GUEST_FS_BASE,
691 VMX_VMCS_GUEST_GS_BASE
692};
693static const uint32_t g_aVmcsSegSel[] =
694{
695 VMX_VMCS16_GUEST_ES_SEL,
696 VMX_VMCS16_GUEST_CS_SEL,
697 VMX_VMCS16_GUEST_SS_SEL,
698 VMX_VMCS16_GUEST_DS_SEL,
699 VMX_VMCS16_GUEST_FS_SEL,
700 VMX_VMCS16_GUEST_GS_SEL
701};
702static const uint32_t g_aVmcsSegLimit[] =
703{
704 VMX_VMCS32_GUEST_ES_LIMIT,
705 VMX_VMCS32_GUEST_CS_LIMIT,
706 VMX_VMCS32_GUEST_SS_LIMIT,
707 VMX_VMCS32_GUEST_DS_LIMIT,
708 VMX_VMCS32_GUEST_FS_LIMIT,
709 VMX_VMCS32_GUEST_GS_LIMIT
710};
711static const uint32_t g_aVmcsSegAttr[] =
712{
713 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
714 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
715 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
716 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
717 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
718 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
719};
720AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
721AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
722AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
723AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
724
725#ifdef HMVMX_USE_FUNCTION_TABLE
726/**
727 * VMX_EXIT dispatch table.
728 */
729static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
730{
731 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
732 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
733 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
734 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
735 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
736 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
737 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
738 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
739 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
740 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
741 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
742 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
743 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
744 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
745 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
746 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
747 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
748 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
749 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
750#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
751 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
752 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
753 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
754 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
755 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
756 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
757 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
758 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
759 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
760#else
761 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
762 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
763 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
764 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
765 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
766 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
767 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
768 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
769 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
770#endif
771 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
772 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
773 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
774 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
775 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
776 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
777 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
778 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
779 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
780 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
781 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
782 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
783 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
784 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
785 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
786 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
787 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
788 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
789 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
790 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
791 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
792 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
793 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
794 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
795 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
796#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
797 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
798#else
799 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
800#endif
801 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
802 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
803 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
804 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
805 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
806 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
807 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
808 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
809 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
810 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
811 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
812 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
813 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
814 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
815 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
816};
817#endif /* HMVMX_USE_FUNCTION_TABLE */
818
819#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
820static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
821{
822 /* 0 */ "(Not Used)",
823 /* 1 */ "VMCALL executed in VMX root operation.",
824 /* 2 */ "VMCLEAR with invalid physical address.",
825 /* 3 */ "VMCLEAR with VMXON pointer.",
826 /* 4 */ "VMLAUNCH with non-clear VMCS.",
827 /* 5 */ "VMRESUME with non-launched VMCS.",
828 /* 6 */ "VMRESUME after VMXOFF",
829 /* 7 */ "VM-entry with invalid control fields.",
830 /* 8 */ "VM-entry with invalid host state fields.",
831 /* 9 */ "VMPTRLD with invalid physical address.",
832 /* 10 */ "VMPTRLD with VMXON pointer.",
833 /* 11 */ "VMPTRLD with incorrect revision identifier.",
834 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
835 /* 13 */ "VMWRITE to read-only VMCS component.",
836 /* 14 */ "(Not Used)",
837 /* 15 */ "VMXON executed in VMX root operation.",
838 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
839 /* 17 */ "VM-entry with non-launched executing VMCS.",
840 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
841 /* 19 */ "VMCALL with non-clear VMCS.",
842 /* 20 */ "VMCALL with invalid VM-exit control fields.",
843 /* 21 */ "(Not Used)",
844 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
845 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
846 /* 24 */ "VMCALL with invalid SMM-monitor features.",
847 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
848 /* 26 */ "VM-entry with events blocked by MOV SS.",
849 /* 27 */ "(Not Used)",
850 /* 28 */ "Invalid operand to INVEPT/INVVPID."
851};
852#endif /* VBOX_STRICT && LOG_ENABLED */
853
854
855/**
856 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
857 *
858 * Any bit set in this mask is owned by the host/hypervisor and would cause a
859 * VM-exit when modified by the guest.
860 *
861 * @returns The static CR0 guest/host mask.
862 * @param pVCpu The cross context virtual CPU structure.
863 */
864DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
865{
866 /*
867 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
868 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
869 */
870 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
871 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
872 * and @bugref{6944}. */
873 PVM pVM = pVCpu->CTX_SUFF(pVM);
874 return ( X86_CR0_PE
875 | X86_CR0_NE
876 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
877 | X86_CR0_PG
878 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
879 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
880 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
881}
882
883
884/**
885 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
886 *
887 * Any bit set in this mask is owned by the host/hypervisor and would cause a
888 * VM-exit when modified by the guest.
889 *
890 * @returns The static CR4 guest/host mask.
891 * @param pVCpu The cross context virtual CPU structure.
892 */
893DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
894{
895 /*
896 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
897 * these bits are reserved on hardware that does not support them. Since the
898 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
899 * these bits and handle it depending on whether we expose them to the guest.
900 */
901 PVM pVM = pVCpu->CTX_SUFF(pVM);
902 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
903 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
904 return ( X86_CR4_VMXE
905 | X86_CR4_VME
906 | X86_CR4_PAE
907 | X86_CR4_PGE
908 | X86_CR4_PSE
909 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
910 | (fPcid ? X86_CR4_PCIDE : 0));
911}
912
913
914/**
915 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
916 * area.
917 *
918 * @returns @c true if it's different, @c false otherwise.
919 * @param pVmcsInfo The VMCS info. object.
920 */
921DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
922{
923 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
924 && pVmcsInfo->pvGuestMsrStore);
925}
926
927
928/**
929 * Sets the given Processor-based VM-execution controls.
930 *
931 * @param pVmxTransient The VMX-transient structure.
932 * @param uProcCtls The Processor-based VM-execution controls to set.
933 */
934static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
935{
936 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
937 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
938 {
939 pVmcsInfo->u32ProcCtls |= uProcCtls;
940 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
941 AssertRC(rc);
942 }
943}
944
945
946/**
947 * Removes the given Processor-based VM-execution controls.
948 *
949 * @param pVCpu The cross context virtual CPU structure.
950 * @param pVmxTransient The VMX-transient structure.
951 * @param uProcCtls The Processor-based VM-execution controls to remove.
952 *
953 * @remarks When executing a nested-guest, this will not remove any of the specified
954 * controls if the guest hypervisor has set any one of them.
955 */
956static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
957{
958 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
959 if (pVmcsInfo->u32ProcCtls & uProcCtls)
960 {
961#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
962 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
963 ? true
964 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
965#else
966 NOREF(pVCpu);
967 bool const fRemoveCtls = true;
968#endif
969 if (fRemoveCtls)
970 {
971 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
972 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
973 AssertRC(rc);
974 }
975 }
976}
977
978
979/**
980 * Sets the TSC offset for the current VMCS.
981 *
982 * @param pVCpu The cross context virtual CPU structure.
983 * @param uTscOffset The TSC offset to set.
984 * @param pVmcsInfo The VMCS info. object.
985 */
986static void hmR0VmxSetTscOffsetVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
987{
988 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
989 if (pVmcsInfo->u64TscOffset != uTscOffset)
990 {
991 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
992 AssertRC(rc);
993 pVmcsInfo->u64TscOffset = uTscOffset;
994 }
995}
996
997
998/**
999 * Adds one or more exceptions to the exception bitmap and commits it to the current
1000 * VMCS.
1001 *
1002 * @returns VBox status code.
1003 * @param pVmxTransient The VMX-transient structure.
1004 * @param uXcptMask The exception(s) to add.
1005 */
1006static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1007{
1008 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1009 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1010 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1011 {
1012 uXcptBitmap |= uXcptMask;
1013 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1014 AssertRCReturn(rc, rc);
1015 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1016 }
1017 return VINF_SUCCESS;
1018}
1019
1020
1021/**
1022 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1023 *
1024 * @returns VBox status code.
1025 * @param pVmxTransient The VMX-transient structure.
1026 * @param uXcpt The exception to add.
1027 */
1028static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1029{
1030 Assert(uXcpt <= X86_XCPT_LAST);
1031 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1032}
1033
1034
1035/**
1036 * Remove one or more exceptions from the exception bitmap and commits it to the
1037 * current VMCS.
1038 *
1039 * This takes care of not removing the exception intercept if a nested-guest
1040 * requires the exception to be intercepted.
1041 *
1042 * @returns VBox status code.
1043 * @param pVCpu The cross context virtual CPU structure.
1044 * @param pVmxTransient The VMX-transient structure.
1045 * @param uXcptMask The exception(s) to remove.
1046 */
1047static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1048{
1049 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1050 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1051 if (u32XcptBitmap & uXcptMask)
1052 {
1053#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1054 if (!pVmxTransient->fIsNestedGuest)
1055 { /* likely */ }
1056 else
1057 {
1058 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1059 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1060 }
1061#endif
1062#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1063 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1064 | RT_BIT(X86_XCPT_DE)
1065 | RT_BIT(X86_XCPT_NM)
1066 | RT_BIT(X86_XCPT_TS)
1067 | RT_BIT(X86_XCPT_UD)
1068 | RT_BIT(X86_XCPT_NP)
1069 | RT_BIT(X86_XCPT_SS)
1070 | RT_BIT(X86_XCPT_GP)
1071 | RT_BIT(X86_XCPT_PF)
1072 | RT_BIT(X86_XCPT_MF));
1073#elif defined(HMVMX_ALWAYS_TRAP_PF)
1074 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1075#endif
1076 if (uXcptMask)
1077 {
1078 /* Validate we are not removing any essential exception intercepts. */
1079 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
1080 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1081 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1082
1083 /* Remove it from the exception bitmap. */
1084 u32XcptBitmap &= ~uXcptMask;
1085
1086 /* Commit and update the cache if necessary. */
1087 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1088 {
1089 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1090 AssertRCReturn(rc, rc);
1091 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1092 }
1093 }
1094 }
1095 return VINF_SUCCESS;
1096}
1097
1098
1099/**
1100 * Remove an exceptions from the exception bitmap and commits it to the current
1101 * VMCS.
1102 *
1103 * @returns VBox status code.
1104 * @param pVCpu The cross context virtual CPU structure.
1105 * @param pVmxTransient The VMX-transient structure.
1106 * @param uXcpt The exception to remove.
1107 */
1108static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1109{
1110 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1111}
1112
1113
1114/**
1115 * Loads the VMCS specified by the VMCS info. object.
1116 *
1117 * @returns VBox status code.
1118 * @param pVmcsInfo The VMCS info. object.
1119 *
1120 * @remarks Can be called with interrupts disabled.
1121 */
1122static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1123{
1124 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1125 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1126
1127 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1128 if (RT_SUCCESS(rc))
1129 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1130 return rc;
1131}
1132
1133
1134/**
1135 * Clears the VMCS specified by the VMCS info. object.
1136 *
1137 * @returns VBox status code.
1138 * @param pVmcsInfo The VMCS info. object.
1139 *
1140 * @remarks Can be called with interrupts disabled.
1141 */
1142static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1143{
1144 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1145 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1146
1147 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1148 if (RT_SUCCESS(rc))
1149 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1150 return rc;
1151}
1152
1153
1154#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1155/**
1156 * Loads the shadow VMCS specified by the VMCS info. object.
1157 *
1158 * @returns VBox status code.
1159 * @param pVmcsInfo The VMCS info. object.
1160 *
1161 * @remarks Can be called with interrupts disabled.
1162 */
1163static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1164{
1165 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1166 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1167
1168 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1169 if (RT_SUCCESS(rc))
1170 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1171 return rc;
1172}
1173
1174
1175/**
1176 * Clears the shadow VMCS specified by the VMCS info. object.
1177 *
1178 * @returns VBox status code.
1179 * @param pVmcsInfo The VMCS info. object.
1180 *
1181 * @remarks Can be called with interrupts disabled.
1182 */
1183static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1184{
1185 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1186 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1187
1188 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1189 if (RT_SUCCESS(rc))
1190 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1191 return rc;
1192}
1193
1194
1195/**
1196 * Switches from and to the specified VMCSes.
1197 *
1198 * @returns VBox status code.
1199 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1200 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1201 *
1202 * @remarks Called with interrupts disabled.
1203 */
1204static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1205{
1206 /*
1207 * Clear the VMCS we are switching out if it has not already been cleared.
1208 * This will sync any CPU internal data back to the VMCS.
1209 */
1210 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1211 {
1212 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1213 if (RT_SUCCESS(rc))
1214 {
1215 /*
1216 * The shadow VMCS, if any, would not be active at this point since we
1217 * would have cleared it while importing the virtual hardware-virtualization
1218 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1219 * clear the shadow VMCS here, just assert for safety.
1220 */
1221 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1222 }
1223 else
1224 return rc;
1225 }
1226
1227 /*
1228 * Clear the VMCS we are switching to if it has not already been cleared.
1229 * This will initialize the VMCS launch state to "clear" required for loading it.
1230 *
1231 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1232 */
1233 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1234 {
1235 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1236 if (RT_SUCCESS(rc))
1237 { /* likely */ }
1238 else
1239 return rc;
1240 }
1241
1242 /*
1243 * Finally, load the VMCS we are switching to.
1244 */
1245 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1246}
1247
1248
1249/**
1250 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1251 * caller.
1252 *
1253 * @returns VBox status code.
1254 * @param pVCpu The cross context virtual CPU structure.
1255 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1256 * true) or guest VMCS (pass false).
1257 */
1258static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1259{
1260 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1261 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1262
1263 PVMXVMCSINFO pVmcsInfoFrom;
1264 PVMXVMCSINFO pVmcsInfoTo;
1265 if (fSwitchToNstGstVmcs)
1266 {
1267 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1268 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1269 }
1270 else
1271 {
1272 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1273 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1274 }
1275
1276 /*
1277 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1278 * preemption hook code path acquires the current VMCS.
1279 */
1280 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1281
1282 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1283 if (RT_SUCCESS(rc))
1284 {
1285 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1286
1287 /*
1288 * If we are switching to a VMCS that was executed on a different host CPU or was
1289 * never executed before, flag that we need to export the host state before executing
1290 * guest/nested-guest code using hardware-assisted VMX.
1291 *
1292 * This could probably be done in a preemptible context since the preemption hook
1293 * will flag the necessary change in host context. However, since preemption is
1294 * already disabled and to avoid making assumptions about host specific code in
1295 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1296 * disabled.
1297 */
1298 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1299 { /* likely */ }
1300 else
1301 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1302
1303 ASMSetFlags(fEFlags);
1304
1305 /*
1306 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1307 * flag that we need to update the host MSR values there. Even if we decide in the
1308 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1309 * if its content differs, we would have to update the host MSRs anyway.
1310 */
1311 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1312 }
1313 else
1314 ASMSetFlags(fEFlags);
1315 return rc;
1316}
1317#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1318
1319
1320/**
1321 * Updates the VM's last error record.
1322 *
1323 * If there was a VMX instruction error, reads the error data from the VMCS and
1324 * updates VCPU's last error record as well.
1325 *
1326 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1327 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1328 * VERR_VMX_INVALID_VMCS_FIELD.
1329 * @param rc The error code.
1330 */
1331static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1332{
1333 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1334 || rc == VERR_VMX_UNABLE_TO_START_VM)
1335 {
1336 AssertPtrReturnVoid(pVCpu);
1337 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1338 }
1339 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1340}
1341
1342
1343#ifdef VBOX_STRICT
1344/**
1345 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1346 * transient structure.
1347 *
1348 * @returns VBox status code.
1349 * @param pVmxTransient The VMX-transient structure.
1350 *
1351 * @remarks No-long-jump zone!!!
1352 */
1353DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1354{
1355 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1356 AssertRCReturn(rc, rc);
1357 return VINF_SUCCESS;
1358}
1359
1360
1361/**
1362 * Reads the VM-entry exception error code field from the VMCS into
1363 * the VMX transient structure.
1364 *
1365 * @returns VBox status code.
1366 * @param pVmxTransient The VMX-transient structure.
1367 *
1368 * @remarks No-long-jump zone!!!
1369 */
1370DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1371{
1372 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1373 AssertRCReturn(rc, rc);
1374 return VINF_SUCCESS;
1375}
1376
1377
1378/**
1379 * Reads the VM-entry exception error code field from the VMCS into
1380 * the VMX transient structure.
1381 *
1382 * @returns VBox status code.
1383 * @param pVmxTransient The VMX-transient structure.
1384 *
1385 * @remarks No-long-jump zone!!!
1386 */
1387DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1388{
1389 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1390 AssertRCReturn(rc, rc);
1391 return VINF_SUCCESS;
1392}
1393#endif /* VBOX_STRICT */
1394
1395
1396/**
1397 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1398 * transient structure.
1399 *
1400 * @returns VBox status code.
1401 * @param pVmxTransient The VMX-transient structure.
1402 */
1403DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1404{
1405 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1406 {
1407 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1408 AssertRCReturn(rc,rc);
1409 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1410 }
1411 return VINF_SUCCESS;
1412}
1413
1414
1415/**
1416 * Reads the VM-exit interruption error code from the VMCS into the VMX
1417 * transient structure.
1418 *
1419 * @returns VBox status code.
1420 * @param pVmxTransient The VMX-transient structure.
1421 */
1422DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1423{
1424 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1425 {
1426 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1427 AssertRCReturn(rc, rc);
1428 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1429 }
1430 return VINF_SUCCESS;
1431}
1432
1433
1434/**
1435 * Reads the VM-exit instruction length field from the VMCS into the VMX
1436 * transient structure.
1437 *
1438 * @returns VBox status code.
1439 * @param pVmxTransient The VMX-transient structure.
1440 */
1441DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1442{
1443 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1444 {
1445 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1446 AssertRCReturn(rc, rc);
1447 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1448 }
1449 return VINF_SUCCESS;
1450}
1451
1452
1453/**
1454 * Reads the VM-exit instruction-information field from the VMCS into
1455 * the VMX transient structure.
1456 *
1457 * @returns VBox status code.
1458 * @param pVmxTransient The VMX-transient structure.
1459 */
1460DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1461{
1462 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1463 {
1464 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1465 AssertRCReturn(rc, rc);
1466 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1467 }
1468 return VINF_SUCCESS;
1469}
1470
1471
1472/**
1473 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1474 *
1475 * @returns VBox status code.
1476 * @param pVCpu The cross context virtual CPU structure of the
1477 * calling EMT. (Required for the VMCS cache case.)
1478 * @param pVmxTransient The VMX-transient structure.
1479 */
1480DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1481{
1482 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1483 {
1484 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1485 AssertRCReturn(rc, rc);
1486 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1487 }
1488 return VINF_SUCCESS;
1489}
1490
1491
1492/**
1493 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1494 *
1495 * @returns VBox status code.
1496 * @param pVCpu The cross context virtual CPU structure of the
1497 * calling EMT. (Required for the VMCS cache case.)
1498 * @param pVmxTransient The VMX-transient structure.
1499 */
1500DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1501{
1502 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1503 {
1504 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1505 AssertRCReturn(rc, rc);
1506 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1507 }
1508 return VINF_SUCCESS;
1509}
1510
1511
1512/**
1513 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1514 *
1515 * @returns VBox status code.
1516 * @param pVCpu The cross context virtual CPU structure of the
1517 * calling EMT. (Required for the VMCS cache case.)
1518 * @param pVmxTransient The VMX-transient structure.
1519 */
1520DECLINLINE(int) hmR0VmxReadGuestPhysicalAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1521{
1522 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1523 {
1524 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr); NOREF(pVCpu);
1525 AssertRCReturn(rc, rc);
1526 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1527 }
1528 return VINF_SUCCESS;
1529}
1530
1531
1532/**
1533 * Reads the IDT-vectoring information field from the VMCS into the VMX
1534 * transient structure.
1535 *
1536 * @returns VBox status code.
1537 * @param pVmxTransient The VMX-transient structure.
1538 *
1539 * @remarks No-long-jump zone!!!
1540 */
1541DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1542{
1543 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1544 {
1545 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1546 AssertRCReturn(rc, rc);
1547 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1548 }
1549 return VINF_SUCCESS;
1550}
1551
1552
1553/**
1554 * Reads the IDT-vectoring error code from the VMCS into the VMX
1555 * transient structure.
1556 *
1557 * @returns VBox status code.
1558 * @param pVmxTransient The VMX-transient structure.
1559 */
1560DECLINLINE(int) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1561{
1562 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1563 {
1564 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1565 AssertRCReturn(rc, rc);
1566 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1567 }
1568 return VINF_SUCCESS;
1569}
1570
1571#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1572/**
1573 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1574 *
1575 * @returns VBox status code.
1576 * @param pVCpu The cross context virtual CPU structure of the
1577 * calling EMT. (Required for the VMCS cache case.)
1578 * @param pVmxTransient The VMX-transient structure.
1579 */
1580static int hmR0VmxReadAllRoFieldsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1581{
1582 NOREF(pVCpu); /* Used implicitly by VMXReadVmcsGstN on 32-bit hosts. */
1583 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1584 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1585 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1586 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1587 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1588 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1589 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1590 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1591 rc |= VMXReadVmcsGstN(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1592 AssertRCReturn(rc, rc);
1593 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1594 | HMVMX_READ_EXIT_INSTR_LEN
1595 | HMVMX_READ_EXIT_INSTR_INFO
1596 | HMVMX_READ_IDT_VECTORING_INFO
1597 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1598 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1599 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1600 | HMVMX_READ_GUEST_LINEAR_ADDR
1601 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1602 return VINF_SUCCESS;
1603}
1604#endif
1605
1606/**
1607 * Enters VMX root mode operation on the current CPU.
1608 *
1609 * @returns VBox status code.
1610 * @param pVM The cross context VM structure. Can be
1611 * NULL, after a resume.
1612 * @param HCPhysCpuPage Physical address of the VMXON region.
1613 * @param pvCpuPage Pointer to the VMXON region.
1614 */
1615static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1616{
1617 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1618 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1619 Assert(pvCpuPage);
1620 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1621
1622 if (pVM)
1623 {
1624 /* Write the VMCS revision identifier to the VMXON region. */
1625 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1626 }
1627
1628 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1629 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1630
1631 /* Enable the VMX bit in CR4 if necessary. */
1632 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1633
1634 /* Enter VMX root mode. */
1635 int rc = VMXEnable(HCPhysCpuPage);
1636 if (RT_FAILURE(rc))
1637 {
1638 if (!(uOldCr4 & X86_CR4_VMXE))
1639 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1640
1641 if (pVM)
1642 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1643 }
1644
1645 /* Restore interrupts. */
1646 ASMSetFlags(fEFlags);
1647 return rc;
1648}
1649
1650
1651/**
1652 * Exits VMX root mode operation on the current CPU.
1653 *
1654 * @returns VBox status code.
1655 */
1656static int hmR0VmxLeaveRootMode(void)
1657{
1658 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1659
1660 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1661 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1662
1663 /* If we're for some reason not in VMX root mode, then don't leave it. */
1664 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1665
1666 int rc;
1667 if (uHostCr4 & X86_CR4_VMXE)
1668 {
1669 /* Exit VMX root mode and clear the VMX bit in CR4. */
1670 VMXDisable();
1671 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1672 rc = VINF_SUCCESS;
1673 }
1674 else
1675 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1676
1677 /* Restore interrupts. */
1678 ASMSetFlags(fEFlags);
1679 return rc;
1680}
1681
1682
1683/**
1684 * Allocates and maps a physically contiguous page. The allocated page is
1685 * zero'd out (used by various VT-x structures).
1686 *
1687 * @returns IPRT status code.
1688 * @param pMemObj Pointer to the ring-0 memory object.
1689 * @param ppVirt Where to store the virtual address of the allocation.
1690 * @param pHCPhys Where to store the physical address of the allocation.
1691 */
1692static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1693{
1694 AssertPtr(pMemObj);
1695 AssertPtr(ppVirt);
1696 AssertPtr(pHCPhys);
1697 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1698 if (RT_FAILURE(rc))
1699 return rc;
1700 *ppVirt = RTR0MemObjAddress(*pMemObj);
1701 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1702 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1703 return VINF_SUCCESS;
1704}
1705
1706
1707/**
1708 * Frees and unmaps an allocated, physical page.
1709 *
1710 * @param pMemObj Pointer to the ring-0 memory object.
1711 * @param ppVirt Where to re-initialize the virtual address of allocation as
1712 * 0.
1713 * @param pHCPhys Where to re-initialize the physical address of the
1714 * allocation as 0.
1715 */
1716static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1717{
1718 AssertPtr(pMemObj);
1719 AssertPtr(ppVirt);
1720 AssertPtr(pHCPhys);
1721 /* NULL is valid, accepted and ignored by the free function below. */
1722 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1723 *pMemObj = NIL_RTR0MEMOBJ;
1724 *ppVirt = NULL;
1725 *pHCPhys = NIL_RTHCPHYS;
1726}
1727
1728
1729/**
1730 * Initializes a VMCS info. object.
1731 *
1732 * @param pVmcsInfo The VMCS info. object.
1733 */
1734static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1735{
1736 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1737
1738 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1739 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1740 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1741 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1742 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1743 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1744 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1745 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1746 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1747 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1748 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1749 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1750 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1751 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1752 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1753 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1754}
1755
1756
1757/**
1758 * Frees the VT-x structures for a VMCS info. object.
1759 *
1760 * @param pVM The cross context VM structure.
1761 * @param pVmcsInfo The VMCS info. object.
1762 */
1763static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1764{
1765 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1766
1767#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1768 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1769 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1770#endif
1771
1772 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1773 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1774
1775 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1776 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1777 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1778
1779 hmR0VmxInitVmcsInfo(pVmcsInfo);
1780}
1781
1782
1783/**
1784 * Allocates the VT-x structures for a VMCS info. object.
1785 *
1786 * @returns VBox status code.
1787 * @param pVCpu The cross context virtual CPU structure.
1788 * @param pVmcsInfo The VMCS info. object.
1789 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1790 */
1791static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1792{
1793 PVM pVM = pVCpu->CTX_SUFF(pVM);
1794
1795 /* Allocate the guest VM control structure (VMCS). */
1796 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1797 if (RT_SUCCESS(rc))
1798 {
1799 if (!fIsNstGstVmcs)
1800 {
1801#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1802 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1803 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1804#endif
1805 if (RT_SUCCESS(rc))
1806 {
1807 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1808 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1809 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1810 {
1811 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1812 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1813 }
1814 }
1815 }
1816 else
1817 {
1818 /* We don't yet support exposing VMCS shadowing to the guest. */
1819 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1820 Assert(!pVmcsInfo->pvShadowVmcs);
1821
1822 /* Get the allocated virtual-APIC page from CPUM. */
1823 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1824 {
1825 /** @todo NSTVMX: Get rid of this. There is no need to allocate a separate HC
1826 * page for this. Use the one provided by the nested-guest directly. */
1827 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1828 &pVmcsInfo->HCPhysVirtApic);
1829 Assert(pVmcsInfo->pbVirtApic);
1830 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1831 }
1832 }
1833
1834 if (RT_SUCCESS(rc))
1835 {
1836 /*
1837 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1838 * transparent accesses of specific MSRs.
1839 *
1840 * If the condition for enabling MSR bitmaps changes here, don't forget to
1841 * update HMIsMsrBitmapActive().
1842 *
1843 * We don't share MSR bitmaps between the guest and nested-guest as we then
1844 * don't need to care about carefully restoring the guest MSR bitmap.
1845 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1846 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1847 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1848 * we do that later while merging VMCS.
1849 */
1850 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1851 {
1852 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1853 if ( RT_SUCCESS(rc)
1854 && !fIsNstGstVmcs)
1855 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1856 }
1857
1858 if (RT_SUCCESS(rc))
1859 {
1860 /*
1861 * Allocate the VM-entry MSR-load area for the guest MSRs.
1862 *
1863 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1864 * the guest and nested-guest.
1865 */
1866 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1867 &pVmcsInfo->HCPhysGuestMsrLoad);
1868 if (RT_SUCCESS(rc))
1869 {
1870 /*
1871 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1872 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1873 */
1874 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1875 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1876 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1877
1878 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1879 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1880 &pVmcsInfo->HCPhysHostMsrLoad);
1881 }
1882 }
1883 }
1884 }
1885
1886 return rc;
1887}
1888
1889
1890/**
1891 * Free all VT-x structures for the VM.
1892 *
1893 * @returns IPRT status code.
1894 * @param pVM The cross context VM structure.
1895 */
1896static void hmR0VmxStructsFree(PVM pVM)
1897{
1898#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1899 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1900#endif
1901 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1902
1903#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1904 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1905 {
1906 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1907 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1908 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1909 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1910 }
1911#endif
1912
1913 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1914 {
1915 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1916 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1917 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1918#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1919 if (pVM->cpum.ro.GuestFeatures.fVmx)
1920 {
1921 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1922 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1923 }
1924#endif
1925 }
1926}
1927
1928
1929/**
1930 * Allocate all VT-x structures for the VM.
1931 *
1932 * @returns IPRT status code.
1933 * @param pVM The cross context VM structure.
1934 */
1935static int hmR0VmxStructsAlloc(PVM pVM)
1936{
1937 /*
1938 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1939 * The VMCS size cannot be more than 4096 bytes.
1940 *
1941 * See Intel spec. Appendix A.1 "Basic VMX Information".
1942 */
1943 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1944 if (cbVmcs <= X86_PAGE_4K_SIZE)
1945 { /* likely */ }
1946 else
1947 {
1948 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1949 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1950 }
1951
1952 /*
1953 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1954 */
1955#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1956 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1957 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1958 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1959#endif
1960
1961 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1962 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1963 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1964
1965 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1966 {
1967 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1968 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1969 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1970 }
1971
1972 /*
1973 * Allocate per-VM VT-x structures.
1974 */
1975 int rc = VINF_SUCCESS;
1976#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1977 /* Allocate crash-dump magic scratch page. */
1978 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1979 if (RT_FAILURE(rc))
1980 {
1981 hmR0VmxStructsFree(pVM);
1982 return rc;
1983 }
1984 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1985 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1986#endif
1987
1988 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1989 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1990 {
1991 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1992 &pVM->hm.s.vmx.HCPhysApicAccess);
1993 if (RT_FAILURE(rc))
1994 {
1995 hmR0VmxStructsFree(pVM);
1996 return rc;
1997 }
1998 }
1999
2000#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2001 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
2002 if (pVM->hm.s.vmx.fUseVmcsShadowing)
2003 {
2004 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
2005 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
2006 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2007 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
2008 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
2009 && pVM->hm.s.vmx.paShadowVmcsRoFields))
2010 {
2011 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
2012 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
2013 if (RT_SUCCESS(rc))
2014 {
2015 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
2016 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
2017 }
2018 }
2019 else
2020 rc = VERR_NO_MEMORY;
2021
2022 if (RT_FAILURE(rc))
2023 {
2024 hmR0VmxStructsFree(pVM);
2025 return rc;
2026 }
2027 }
2028#endif
2029
2030 /*
2031 * Initialize per-VCPU VT-x structures.
2032 */
2033 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2034 {
2035 /* Allocate the guest VMCS structures. */
2036 PVMCPU pVCpu = &pVM->aCpus[idCpu];
2037 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2038 if (RT_SUCCESS(rc))
2039 {
2040#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2041 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2042 if (pVM->cpum.ro.GuestFeatures.fVmx)
2043 {
2044 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2045 if (RT_SUCCESS(rc))
2046 { /* likely */ }
2047 else
2048 break;
2049 }
2050#endif
2051 }
2052 else
2053 break;
2054 }
2055
2056 if (RT_FAILURE(rc))
2057 {
2058 hmR0VmxStructsFree(pVM);
2059 return rc;
2060 }
2061
2062 return VINF_SUCCESS;
2063}
2064
2065#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2066/**
2067 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2068 *
2069 * @returns @c true if the MSR is intercepted, @c false otherwise.
2070 * @param pvMsrBitmap The MSR bitmap.
2071 * @param offMsr The MSR byte offset.
2072 * @param iBit The bit offset from the byte offset.
2073 */
2074DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2075{
2076 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2077 Assert(pbMsrBitmap);
2078 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2079 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2080}
2081#endif
2082
2083/**
2084 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2085 *
2086 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2087 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2088 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2089 * the read/write access of this MSR.
2090 *
2091 * @param pVCpu The cross context virtual CPU structure.
2092 * @param pVmcsInfo The VMCS info. object.
2093 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2094 * @param idMsr The MSR value.
2095 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2096 * include both a read -and- a write permission!
2097 *
2098 * @sa CPUMGetVmxMsrPermission.
2099 * @remarks Can be called with interrupts disabled.
2100 */
2101static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2102{
2103 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2104 Assert(pbMsrBitmap);
2105 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2106
2107 /*
2108 * MSR-bitmap Layout:
2109 * Byte index MSR range Interpreted as
2110 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2111 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2112 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2113 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2114 *
2115 * A bit corresponding to an MSR within the above range causes a VM-exit
2116 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2117 * the MSR range, it always cause a VM-exit.
2118 *
2119 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2120 */
2121 uint16_t const offBitmapRead = 0;
2122 uint16_t const offBitmapWrite = 0x800;
2123 uint16_t offMsr;
2124 int32_t iBit;
2125 if (idMsr <= UINT32_C(0x00001fff))
2126 {
2127 offMsr = 0;
2128 iBit = idMsr;
2129 }
2130 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2131 {
2132 offMsr = 0x400;
2133 iBit = idMsr - UINT32_C(0xc0000000);
2134 }
2135 else
2136 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2137
2138 /*
2139 * Set the MSR read permission.
2140 */
2141 uint16_t const offMsrRead = offBitmapRead + offMsr;
2142 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2143 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2144 {
2145#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2146 bool const fClear = !fIsNstGstVmcs ? true
2147 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2148#else
2149 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2150 bool const fClear = true;
2151#endif
2152 if (fClear)
2153 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2154 }
2155 else
2156 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2157
2158 /*
2159 * Set the MSR write permission.
2160 */
2161 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2162 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2163 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2164 {
2165#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2166 bool const fClear = !fIsNstGstVmcs ? true
2167 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2168#else
2169 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2170 bool const fClear = true;
2171#endif
2172 if (fClear)
2173 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2174 }
2175 else
2176 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2177}
2178
2179
2180/**
2181 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2182 * area.
2183 *
2184 * @returns VBox status code.
2185 * @param pVCpu The cross context virtual CPU structure.
2186 * @param pVmcsInfo The VMCS info. object.
2187 * @param cMsrs The number of MSRs.
2188 */
2189static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2190{
2191 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2192 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2193 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2194 {
2195 /* Commit the MSR counts to the VMCS and update the cache. */
2196 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2197 {
2198 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
2199 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
2200 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
2201 AssertRCReturn(rc, rc);
2202
2203 pVmcsInfo->cEntryMsrLoad = cMsrs;
2204 pVmcsInfo->cExitMsrStore = cMsrs;
2205 pVmcsInfo->cExitMsrLoad = cMsrs;
2206 }
2207 return VINF_SUCCESS;
2208 }
2209
2210 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2211 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2212 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2213}
2214
2215
2216/**
2217 * Adds a new (or updates the value of an existing) guest/host MSR
2218 * pair to be swapped during the world-switch as part of the
2219 * auto-load/store MSR area in the VMCS.
2220 *
2221 * @returns VBox status code.
2222 * @param pVCpu The cross context virtual CPU structure.
2223 * @param pVmxTransient The VMX-transient structure.
2224 * @param idMsr The MSR.
2225 * @param uGuestMsrValue Value of the guest MSR.
2226 * @param fSetReadWrite Whether to set the guest read/write access of this
2227 * MSR (thus not causing a VM-exit).
2228 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2229 * necessary.
2230 */
2231static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2232 bool fSetReadWrite, bool fUpdateHostMsr)
2233{
2234 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2235 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2236 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2237 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2238 uint32_t i;
2239
2240 /* Paranoia. */
2241 Assert(pGuestMsrLoad);
2242
2243 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2244
2245 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2246 for (i = 0; i < cMsrs; i++)
2247 {
2248 if (pGuestMsrLoad[i].u32Msr == idMsr)
2249 break;
2250 }
2251
2252 bool fAdded = false;
2253 if (i == cMsrs)
2254 {
2255 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2256 ++cMsrs;
2257 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2258 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2259
2260 /* Set the guest to read/write this MSR without causing VM-exits. */
2261 if ( fSetReadWrite
2262 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2263 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2264
2265 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2266 fAdded = true;
2267 }
2268
2269 /* Update the MSR value for the newly added or already existing MSR. */
2270 pGuestMsrLoad[i].u32Msr = idMsr;
2271 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2272
2273 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2274 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2275 {
2276 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2277 pGuestMsrStore[i].u32Msr = idMsr;
2278 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2279 }
2280
2281 /* Update the corresponding slot in the host MSR area. */
2282 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2283 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2284 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2285 pHostMsr[i].u32Msr = idMsr;
2286
2287 /*
2288 * Only if the caller requests to update the host MSR value AND we've newly added the
2289 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2290 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2291 *
2292 * We do this for performance reasons since reading MSRs may be quite expensive.
2293 */
2294 if (fAdded)
2295 {
2296 if (fUpdateHostMsr)
2297 {
2298 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2299 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2300 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2301 }
2302 else
2303 {
2304 /* Someone else can do the work. */
2305 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2306 }
2307 }
2308 return VINF_SUCCESS;
2309}
2310
2311
2312/**
2313 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2314 * auto-load/store MSR area in the VMCS.
2315 *
2316 * @returns VBox status code.
2317 * @param pVCpu The cross context virtual CPU structure.
2318 * @param pVmxTransient The VMX-transient structure.
2319 * @param idMsr The MSR.
2320 */
2321static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2322{
2323 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2324 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2325 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2326 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2327
2328 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2329
2330 for (uint32_t i = 0; i < cMsrs; i++)
2331 {
2332 /* Find the MSR. */
2333 if (pGuestMsrLoad[i].u32Msr == idMsr)
2334 {
2335 /*
2336 * If it's the last MSR, we only need to reduce the MSR count.
2337 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2338 */
2339 if (i < cMsrs - 1)
2340 {
2341 /* Remove it from the VM-entry MSR-load area. */
2342 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2343 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2344
2345 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2346 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2347 {
2348 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2349 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2350 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2351 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2352 }
2353
2354 /* Remove it from the VM-exit MSR-load area. */
2355 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2356 Assert(pHostMsr[i].u32Msr == idMsr);
2357 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2358 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2359 }
2360
2361 /* Reduce the count to reflect the removed MSR and bail. */
2362 --cMsrs;
2363 break;
2364 }
2365 }
2366
2367 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2368 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2369 {
2370 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2371 AssertRCReturn(rc, rc);
2372
2373 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2374 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2375 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2376
2377 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2378 return VINF_SUCCESS;
2379 }
2380
2381 return VERR_NOT_FOUND;
2382}
2383
2384
2385/**
2386 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2387 *
2388 * @returns @c true if found, @c false otherwise.
2389 * @param pVmcsInfo The VMCS info. object.
2390 * @param idMsr The MSR to find.
2391 */
2392static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2393{
2394 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2395 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2396 Assert(pMsrs);
2397 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2398 for (uint32_t i = 0; i < cMsrs; i++)
2399 {
2400 if (pMsrs[i].u32Msr == idMsr)
2401 return true;
2402 }
2403 return false;
2404}
2405
2406
2407/**
2408 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2409 *
2410 * @param pVCpu The cross context virtual CPU structure.
2411 * @param pVmcsInfo The VMCS info. object.
2412 *
2413 * @remarks No-long-jump zone!!!
2414 */
2415static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2416{
2417 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2418
2419 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2420 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2421 Assert(pHostMsrLoad);
2422 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2423 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2424 for (uint32_t i = 0; i < cMsrs; i++)
2425 {
2426 /*
2427 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2428 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2429 */
2430 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2431 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2432 else
2433 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2434 }
2435}
2436
2437
2438/**
2439 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2440 * perform lazy restoration of the host MSRs while leaving VT-x.
2441 *
2442 * @param pVCpu The cross context virtual CPU structure.
2443 *
2444 * @remarks No-long-jump zone!!!
2445 */
2446static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2447{
2448 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2449
2450 /*
2451 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2452 */
2453 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2454 {
2455 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2456#if HC_ARCH_BITS == 64
2457 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2458 {
2459 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2460 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2461 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2462 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2463 }
2464#endif
2465 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2466 }
2467}
2468
2469
2470/**
2471 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2472 * lazily while leaving VT-x.
2473 *
2474 * @returns true if it does, false otherwise.
2475 * @param pVCpu The cross context virtual CPU structure.
2476 * @param idMsr The MSR to check.
2477 */
2478static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2479{
2480 NOREF(pVCpu);
2481#if HC_ARCH_BITS == 64
2482 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2483 {
2484 switch (idMsr)
2485 {
2486 case MSR_K8_LSTAR:
2487 case MSR_K6_STAR:
2488 case MSR_K8_SF_MASK:
2489 case MSR_K8_KERNEL_GS_BASE:
2490 return true;
2491 }
2492 }
2493#else
2494 RT_NOREF(pVCpu, idMsr);
2495#endif
2496 return false;
2497}
2498
2499
2500/**
2501 * Loads a set of guests MSRs to allow read/passthru to the guest.
2502 *
2503 * The name of this function is slightly confusing. This function does NOT
2504 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2505 * common prefix for functions dealing with "lazy restoration" of the shared
2506 * MSRs.
2507 *
2508 * @param pVCpu The cross context virtual CPU structure.
2509 *
2510 * @remarks No-long-jump zone!!!
2511 */
2512static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2513{
2514 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2515 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2516
2517 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2518#if HC_ARCH_BITS == 64
2519 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2520 {
2521 /*
2522 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2523 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2524 * we can skip a few MSR writes.
2525 *
2526 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2527 * guest MSR values in the guest-CPU context might be different to what's currently
2528 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2529 * CPU, see @bugref{8728}.
2530 */
2531 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2532 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2533 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2534 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2535 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2536 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2537 {
2538#ifdef VBOX_STRICT
2539 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2540 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2541 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2542 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2543#endif
2544 }
2545 else
2546 {
2547 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2548 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2549 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2550 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2551 }
2552 }
2553#endif
2554 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2555}
2556
2557
2558/**
2559 * Performs lazy restoration of the set of host MSRs if they were previously
2560 * loaded with guest MSR values.
2561 *
2562 * @param pVCpu The cross context virtual CPU structure.
2563 *
2564 * @remarks No-long-jump zone!!!
2565 * @remarks The guest MSRs should have been saved back into the guest-CPU
2566 * context by hmR0VmxImportGuestState()!!!
2567 */
2568static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2569{
2570 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2571 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2572
2573 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2574 {
2575 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2576#if HC_ARCH_BITS == 64
2577 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2578 {
2579 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2580 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2581 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2582 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2583 }
2584#endif
2585 }
2586 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2587}
2588
2589
2590/**
2591 * Verifies that our cached values of the VMCS fields are all consistent with
2592 * what's actually present in the VMCS.
2593 *
2594 * @returns VBox status code.
2595 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2596 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2597 * VMCS content. HMCPU error-field is
2598 * updated, see VMX_VCI_XXX.
2599 * @param pVCpu The cross context virtual CPU structure.
2600 * @param pVmcsInfo The VMCS info. object.
2601 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2602 */
2603static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2604{
2605 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2606
2607 uint32_t u32Val;
2608 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2609 AssertRCReturn(rc, rc);
2610 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2611 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2612 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2613 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2614
2615 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2616 AssertRCReturn(rc, rc);
2617 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2618 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2619 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2620 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2621
2622 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2623 AssertRCReturn(rc, rc);
2624 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2625 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2626 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2627 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2628
2629 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2630 AssertRCReturn(rc, rc);
2631 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2632 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2633 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2634 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2635
2636 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2637 {
2638 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2639 AssertRCReturn(rc, rc);
2640 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2641 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2642 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2643 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2644 }
2645
2646 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2647 AssertRCReturn(rc, rc);
2648 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2649 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2650 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2651 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2652
2653 uint64_t u64Val;
2654 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2655 AssertRCReturn(rc, rc);
2656 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2657 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2658 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2659 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2660
2661 NOREF(pcszVmcs);
2662 return VINF_SUCCESS;
2663}
2664
2665
2666#ifdef VBOX_STRICT
2667/**
2668 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2669 *
2670 * @param pVCpu The cross context virtual CPU structure.
2671 * @param pVmcsInfo The VMCS info. object.
2672 */
2673static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2674{
2675 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2676
2677 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2678 {
2679 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2680 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2681 uint64_t uVmcsEferMsrVmcs;
2682 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2683 AssertRC(rc);
2684
2685 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2686 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2687 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2688 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2689 }
2690}
2691
2692
2693/**
2694 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2695 * VMCS are correct.
2696 *
2697 * @param pVCpu The cross context virtual CPU structure.
2698 * @param pVmcsInfo The VMCS info. object.
2699 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2700 */
2701static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2702{
2703 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2704
2705 /* Read the various MSR-area counts from the VMCS. */
2706 uint32_t cEntryLoadMsrs;
2707 uint32_t cExitStoreMsrs;
2708 uint32_t cExitLoadMsrs;
2709 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2710 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2711 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2712
2713 /* Verify all the MSR counts are the same. */
2714 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2715 Assert(cExitStoreMsrs == cExitLoadMsrs);
2716 uint32_t const cMsrs = cExitLoadMsrs;
2717
2718 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2719 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2720
2721 /* Verify the MSR counts are within the allocated page size. */
2722 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2723
2724 /* Verify the relevant contents of the MSR areas match. */
2725 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2726 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2727 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2728 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2729 for (uint32_t i = 0; i < cMsrs; i++)
2730 {
2731 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2732 if (fSeparateExitMsrStorePage)
2733 {
2734 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2735 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2736 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2737 }
2738
2739 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2740 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2741 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2742
2743 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2744 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2745 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2746 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2747
2748 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2749 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2750 if (fIsEferMsr)
2751 {
2752 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2753 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2754 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2755 }
2756
2757 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2758 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2759 {
2760 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2761 if (fIsEferMsr)
2762 {
2763 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2764 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2765 }
2766 else
2767 {
2768 if (!fIsNstGstVmcs)
2769 {
2770 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2771 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2772 }
2773 else
2774 {
2775 /*
2776 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2777 * execute a nested-guest with MSR passthrough.
2778 *
2779 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2780 * allow passthrough too.
2781 */
2782 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2783 Assert(pvMsrBitmapNstGst);
2784 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2785 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2786 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2787 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2788 }
2789 }
2790 }
2791
2792 /* Move to the next MSR. */
2793 pHostMsrLoad++;
2794 pGuestMsrLoad++;
2795 pGuestMsrStore++;
2796 }
2797}
2798#endif /* VBOX_STRICT */
2799
2800
2801/**
2802 * Flushes the TLB using EPT.
2803 *
2804 * @returns VBox status code.
2805 * @param pVCpu The cross context virtual CPU structure of the calling
2806 * EMT. Can be NULL depending on @a enmTlbFlush.
2807 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2808 * enmTlbFlush.
2809 * @param enmTlbFlush Type of flush.
2810 *
2811 * @remarks Caller is responsible for making sure this function is called only
2812 * when NestedPaging is supported and providing @a enmTlbFlush that is
2813 * supported by the CPU.
2814 * @remarks Can be called with interrupts disabled.
2815 */
2816static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2817{
2818 uint64_t au64Descriptor[2];
2819 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2820 au64Descriptor[0] = 0;
2821 else
2822 {
2823 Assert(pVCpu);
2824 Assert(pVmcsInfo);
2825 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2826 }
2827 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2828
2829 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2830 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2831
2832 if ( RT_SUCCESS(rc)
2833 && pVCpu)
2834 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2835}
2836
2837
2838/**
2839 * Flushes the TLB using VPID.
2840 *
2841 * @returns VBox status code.
2842 * @param pVCpu The cross context virtual CPU structure of the calling
2843 * EMT. Can be NULL depending on @a enmTlbFlush.
2844 * @param enmTlbFlush Type of flush.
2845 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2846 * on @a enmTlbFlush).
2847 *
2848 * @remarks Can be called with interrupts disabled.
2849 */
2850static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2851{
2852 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2853
2854 uint64_t au64Descriptor[2];
2855 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2856 {
2857 au64Descriptor[0] = 0;
2858 au64Descriptor[1] = 0;
2859 }
2860 else
2861 {
2862 AssertPtr(pVCpu);
2863 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2864 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2865 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2866 au64Descriptor[1] = GCPtr;
2867 }
2868
2869 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2870 AssertMsg(rc == VINF_SUCCESS,
2871 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2872
2873 if ( RT_SUCCESS(rc)
2874 && pVCpu)
2875 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2876 NOREF(rc);
2877}
2878
2879
2880/**
2881 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2882 * otherwise there is nothing really to invalidate.
2883 *
2884 * @returns VBox status code.
2885 * @param pVCpu The cross context virtual CPU structure.
2886 * @param GCVirt Guest virtual address of the page to invalidate.
2887 */
2888VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2889{
2890 AssertPtr(pVCpu);
2891 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2892
2893 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2894 {
2895 /*
2896 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2897 * the EPT case. See @bugref{6043} and @bugref{6177}.
2898 *
2899 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2900 * as this function maybe called in a loop with individual addresses.
2901 */
2902 PVM pVM = pVCpu->CTX_SUFF(pVM);
2903 if (pVM->hm.s.vmx.fVpid)
2904 {
2905 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2906
2907#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2908 /*
2909 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2910 * where executing INVVPID outside 64-bit mode does not flush translations of
2911 * 64-bit linear addresses, see @bugref{6208#c72}.
2912 */
2913 if (RT_HI_U32(GCVirt))
2914 fVpidFlush = false;
2915#endif
2916
2917 if (fVpidFlush)
2918 {
2919 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2920 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2921 }
2922 else
2923 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2924 }
2925 else if (pVM->hm.s.fNestedPaging)
2926 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2927 }
2928
2929 return VINF_SUCCESS;
2930}
2931
2932
2933/**
2934 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2935 * case where neither EPT nor VPID is supported by the CPU.
2936 *
2937 * @param pHostCpu The HM physical-CPU structure.
2938 * @param pVCpu The cross context virtual CPU structure.
2939 *
2940 * @remarks Called with interrupts disabled.
2941 */
2942static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2943{
2944 AssertPtr(pVCpu);
2945 AssertPtr(pHostCpu);
2946
2947 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2948
2949 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2950 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2951 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2952 pVCpu->hm.s.fForceTLBFlush = false;
2953 return;
2954}
2955
2956
2957/**
2958 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2959 *
2960 * @param pHostCpu The HM physical-CPU structure.
2961 * @param pVCpu The cross context virtual CPU structure.
2962 * @param pVmcsInfo The VMCS info. object.
2963 *
2964 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2965 * nomenclature. The reason is, to avoid confusion in compare statements
2966 * since the host-CPU copies are named "ASID".
2967 *
2968 * @remarks Called with interrupts disabled.
2969 */
2970static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2971{
2972#ifdef VBOX_WITH_STATISTICS
2973 bool fTlbFlushed = false;
2974# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2975# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2976 if (!fTlbFlushed) \
2977 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2978 } while (0)
2979#else
2980# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2981# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2982#endif
2983
2984 AssertPtr(pVCpu);
2985 AssertPtr(pHostCpu);
2986 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2987
2988 PVM pVM = pVCpu->CTX_SUFF(pVM);
2989 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2990 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2991 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2992
2993 /*
2994 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2995 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2996 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2997 * cannot reuse the current ASID anymore.
2998 */
2999 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3000 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3001 {
3002 ++pHostCpu->uCurrentAsid;
3003 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3004 {
3005 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
3006 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3007 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3008 }
3009
3010 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3011 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3012 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3013
3014 /*
3015 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
3016 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
3017 */
3018 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3019 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3020 HMVMX_SET_TAGGED_TLB_FLUSHED();
3021 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
3022 }
3023 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
3024 {
3025 /*
3026 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
3027 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
3028 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
3029 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
3030 * mappings, see @bugref{6568}.
3031 *
3032 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
3033 */
3034 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3035 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3036 HMVMX_SET_TAGGED_TLB_FLUSHED();
3037 }
3038 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3039 {
3040 /*
3041 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3042 * address which requires flushing the TLB of EPT cached structures.
3043 *
3044 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3045 */
3046 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3047 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3048 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3049 HMVMX_SET_TAGGED_TLB_FLUSHED();
3050 }
3051
3052
3053 pVCpu->hm.s.fForceTLBFlush = false;
3054 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3055
3056 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
3057 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3058 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3059 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3060 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3061 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3062 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3063 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3064 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3065
3066 /* Update VMCS with the VPID. */
3067 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3068 AssertRC(rc);
3069
3070#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3071}
3072
3073
3074/**
3075 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3076 *
3077 * @param pHostCpu The HM physical-CPU structure.
3078 * @param pVCpu The cross context virtual CPU structure.
3079 * @param pVmcsInfo The VMCS info. object.
3080 *
3081 * @remarks Called with interrupts disabled.
3082 */
3083static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3084{
3085 AssertPtr(pVCpu);
3086 AssertPtr(pHostCpu);
3087 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3088 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3089 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3090
3091 /*
3092 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3093 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3094 */
3095 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3096 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3097 {
3098 pVCpu->hm.s.fForceTLBFlush = true;
3099 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3100 }
3101
3102 /* Check for explicit TLB flushes. */
3103 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3104 {
3105 pVCpu->hm.s.fForceTLBFlush = true;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3107 }
3108
3109 /* Check for TLB flushes while switching to/from a nested-guest. */
3110 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3111 {
3112 pVCpu->hm.s.fForceTLBFlush = true;
3113 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3114 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3115 }
3116
3117 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3118 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3119
3120 if (pVCpu->hm.s.fForceTLBFlush)
3121 {
3122 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3123 pVCpu->hm.s.fForceTLBFlush = false;
3124 }
3125}
3126
3127
3128/**
3129 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3130 *
3131 * @param pHostCpu The HM physical-CPU structure.
3132 * @param pVCpu The cross context virtual CPU structure.
3133 *
3134 * @remarks Called with interrupts disabled.
3135 */
3136static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3137{
3138 AssertPtr(pVCpu);
3139 AssertPtr(pHostCpu);
3140 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3141 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3142 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3143
3144 /*
3145 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3146 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3147 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3148 * cannot reuse the current ASID anymore.
3149 */
3150 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3151 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3152 {
3153 pVCpu->hm.s.fForceTLBFlush = true;
3154 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3155 }
3156
3157 /* Check for explicit TLB flushes. */
3158 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3159 {
3160 /*
3161 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3162 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3163 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3164 * include fExplicitFlush's too) - an obscure corner case.
3165 */
3166 pVCpu->hm.s.fForceTLBFlush = true;
3167 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3168 }
3169
3170 /* Check for TLB flushes while switching to/from a nested-guest. */
3171 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3172 {
3173 pVCpu->hm.s.fForceTLBFlush = true;
3174 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3175 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3176 }
3177
3178 PVM pVM = pVCpu->CTX_SUFF(pVM);
3179 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3180 if (pVCpu->hm.s.fForceTLBFlush)
3181 {
3182 ++pHostCpu->uCurrentAsid;
3183 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3184 {
3185 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3186 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3187 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3188 }
3189
3190 pVCpu->hm.s.fForceTLBFlush = false;
3191 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3192 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3193 if (pHostCpu->fFlushAsidBeforeUse)
3194 {
3195 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3196 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3197 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3198 {
3199 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3200 pHostCpu->fFlushAsidBeforeUse = false;
3201 }
3202 else
3203 {
3204 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3205 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3206 }
3207 }
3208 }
3209
3210 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3211 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3212 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3213 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3214 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3215 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3216 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3217
3218 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3219 AssertRC(rc);
3220}
3221
3222
3223/**
3224 * Flushes the guest TLB entry based on CPU capabilities.
3225 *
3226 * @param pHostCpu The HM physical-CPU structure.
3227 * @param pVCpu The cross context virtual CPU structure.
3228 * @param pVmcsInfo The VMCS info. object.
3229 *
3230 * @remarks Called with interrupts disabled.
3231 */
3232static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3233{
3234#ifdef HMVMX_ALWAYS_FLUSH_TLB
3235 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3236#endif
3237 PVM pVM = pVCpu->CTX_SUFF(pVM);
3238 switch (pVM->hm.s.vmx.enmTlbFlushType)
3239 {
3240 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3241 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3242 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3243 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3244 default:
3245 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3246 break;
3247 }
3248 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3249}
3250
3251
3252/**
3253 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3254 * TLB entries from the host TLB before VM-entry.
3255 *
3256 * @returns VBox status code.
3257 * @param pVM The cross context VM structure.
3258 */
3259static int hmR0VmxSetupTaggedTlb(PVM pVM)
3260{
3261 /*
3262 * Determine optimal flush type for nested paging.
3263 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3264 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3265 */
3266 if (pVM->hm.s.fNestedPaging)
3267 {
3268 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3269 {
3270 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3271 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3272 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3273 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3274 else
3275 {
3276 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3277 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3278 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3279 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3280 }
3281
3282 /* Make sure the write-back cacheable memory type for EPT is supported. */
3283 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3284 {
3285 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3286 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3287 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3288 }
3289
3290 /* EPT requires a page-walk length of 4. */
3291 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3292 {
3293 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3294 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3295 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3296 }
3297 }
3298 else
3299 {
3300 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3301 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3302 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3303 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3304 }
3305 }
3306
3307 /*
3308 * Determine optimal flush type for VPID.
3309 */
3310 if (pVM->hm.s.vmx.fVpid)
3311 {
3312 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3313 {
3314 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3315 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3316 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3317 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3318 else
3319 {
3320 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3321 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3322 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3323 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3324 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3325 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3326 pVM->hm.s.vmx.fVpid = false;
3327 }
3328 }
3329 else
3330 {
3331 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3332 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3333 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3334 pVM->hm.s.vmx.fVpid = false;
3335 }
3336 }
3337
3338 /*
3339 * Setup the handler for flushing tagged-TLBs.
3340 */
3341 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3342 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3343 else if (pVM->hm.s.fNestedPaging)
3344 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3345 else if (pVM->hm.s.vmx.fVpid)
3346 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3347 else
3348 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3349 return VINF_SUCCESS;
3350}
3351
3352
3353#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3354/**
3355 * Sets up the shadow VMCS fields arrays.
3356 *
3357 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3358 * executing the guest.
3359 *
3360 * @returns VBox status code.
3361 * @param pVM The cross context VM structure.
3362 */
3363static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3364{
3365 /*
3366 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3367 * when the host does not support it.
3368 */
3369 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3370 if ( !fGstVmwriteAll
3371 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3372 { /* likely. */ }
3373 else
3374 {
3375 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3376 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3377 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3378 }
3379
3380 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3381 uint32_t cRwFields = 0;
3382 uint32_t cRoFields = 0;
3383 for (uint32_t i = 0; i < cVmcsFields; i++)
3384 {
3385 VMXVMCSFIELD VmcsField;
3386 VmcsField.u = g_aVmcsFields[i];
3387
3388 /*
3389 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3390 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3391 * in the shadow VMCS fields array as they would be redundant.
3392 *
3393 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3394 * we must not include it in the shadow VMCS fields array. Guests attempting to
3395 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3396 * the required behavior.
3397 */
3398 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3399 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3400 {
3401 /*
3402 * Read-only fields are placed in a separate array so that while syncing shadow
3403 * VMCS fields later (which is more performance critical) we can avoid branches.
3404 *
3405 * However, if the guest can write to all fields (including read-only fields),
3406 * we treat it a as read/write field. Otherwise, writing to these fields would
3407 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3408 */
3409 if ( fGstVmwriteAll
3410 || !HMVmxIsVmcsFieldReadOnly(VmcsField.u))
3411 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3412 else
3413 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3414 }
3415 }
3416
3417 /* Update the counts. */
3418 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3419 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3420 return VINF_SUCCESS;
3421}
3422
3423
3424/**
3425 * Sets up the VMREAD and VMWRITE bitmaps.
3426 *
3427 * @param pVM The cross context VM structure.
3428 */
3429static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3430{
3431 /*
3432 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3433 */
3434 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3435 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3436 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3437 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3438 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3439
3440 /*
3441 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3442 * VMREAD and VMWRITE bitmaps.
3443 */
3444 {
3445 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3446 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3447 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3448 {
3449 uint32_t const uVmcsField = paShadowVmcsFields[i];
3450 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3451 Assert(uVmcsField >> 3 < cbBitmap);
3452 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3453 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3454 }
3455 }
3456
3457 /*
3458 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3459 * if the host supports VMWRITE to all supported VMCS fields.
3460 */
3461 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3462 {
3463 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3464 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3465 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3466 {
3467 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3468 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3469 Assert(uVmcsField >> 3 < cbBitmap);
3470 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3471 }
3472 }
3473}
3474#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3475
3476
3477/**
3478 * Sets up the virtual-APIC page address for the VMCS.
3479 *
3480 * @returns VBox status code.
3481 * @param pVCpu The cross context virtual CPU structure.
3482 * @param pVmcsInfo The VMCS info. object.
3483 */
3484DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3485{
3486 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3487 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3488 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3489 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3490 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3491}
3492
3493
3494/**
3495 * Sets up the MSR-bitmap address for the VMCS.
3496 *
3497 * @returns VBox status code.
3498 * @param pVCpu The cross context virtual CPU structure.
3499 * @param pVmcsInfo The VMCS info. object.
3500 */
3501DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3502{
3503 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3504 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3505 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3506 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3507 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3508}
3509
3510
3511/**
3512 * Sets up the APIC-access page address for the VMCS.
3513 *
3514 * @returns VBox status code.
3515 * @param pVCpu The cross context virtual CPU structure.
3516 */
3517DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3518{
3519 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3520 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3521 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3522 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3523}
3524
3525
3526#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3527/**
3528 * Sets up the VMREAD bitmap address for the VMCS.
3529 *
3530 * @returns VBox status code.
3531 * @param pVCpu The cross context virtual CPU structure.
3532 */
3533DECLINLINE(int) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3534{
3535 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3536 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3537 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3538 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3539}
3540
3541
3542/**
3543 * Sets up the VMWRITE bitmap address for the VMCS.
3544 *
3545 * @returns VBox status code.
3546 * @param pVCpu The cross context virtual CPU structure.
3547 */
3548DECLINLINE(int) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3549{
3550 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3551 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3552 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3553 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3554}
3555#endif
3556
3557
3558/**
3559 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3560 * in the VMCS.
3561 *
3562 * @returns VBox status code.
3563 * @param pVCpu The cross context virtual CPU structure.
3564 * @param pVmcsInfo The VMCS info. object.
3565 */
3566DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3567{
3568 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3569
3570 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3571 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3572 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3573
3574 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3575 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3576 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3577
3578 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3579 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3580 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3581
3582 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
3583 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
3584 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
3585 AssertRCReturn(rc, rc);
3586 return VINF_SUCCESS;
3587}
3588
3589
3590/**
3591 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3592 *
3593 * @param pVCpu The cross context virtual CPU structure.
3594 * @param pVmcsInfo The VMCS info. object.
3595 */
3596static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3597{
3598 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3599
3600 /*
3601 * The guest can access the following MSRs (read, write) without causing
3602 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3603 */
3604 PVM pVM = pVCpu->CTX_SUFF(pVM);
3605 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3606 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3607 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3608 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3609 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3610
3611 /*
3612 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3613 * associated with then. We never need to intercept access (writes need to be
3614 * executed without causing a VM-exit, reads will #GP fault anyway).
3615 *
3616 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3617 * read/write them. We swap the the guest/host MSR value using the
3618 * auto-load/store MSR area.
3619 */
3620 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3621 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3622 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3623 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3624 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3625 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3626
3627#if HC_ARCH_BITS == 64
3628 /*
3629 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3630 * required for 64-bit guests.
3631 */
3632 if (pVM->hm.s.fAllow64BitGuests)
3633 {
3634 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3635 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3636 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3637 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3638 }
3639#endif
3640
3641 /*
3642 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3643 */
3644#ifdef VBOX_STRICT
3645 Assert(pVmcsInfo->pvMsrBitmap);
3646 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3647 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3648#endif
3649}
3650
3651
3652/**
3653 * Sets up pin-based VM-execution controls in the VMCS.
3654 *
3655 * @returns VBox status code.
3656 * @param pVCpu The cross context virtual CPU structure.
3657 * @param pVmcsInfo The VMCS info. object.
3658 */
3659static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3660{
3661 PVM pVM = pVCpu->CTX_SUFF(pVM);
3662 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3663 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3664
3665 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3666 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3667
3668 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3669 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3670
3671 /* Enable the VMX-preemption timer. */
3672 if (pVM->hm.s.vmx.fUsePreemptTimer)
3673 {
3674 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3675 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3676 }
3677
3678#if 0
3679 /* Enable posted-interrupt processing. */
3680 if (pVM->hm.s.fPostedIntrs)
3681 {
3682 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3683 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3684 fVal |= VMX_PIN_CTLS_POSTED_INT;
3685 }
3686#endif
3687
3688 if ((fVal & fZap) != fVal)
3689 {
3690 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3691 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3692 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3693 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3694 }
3695
3696 /* Commit it to the VMCS and update our cache. */
3697 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3698 AssertRCReturn(rc, rc);
3699 pVmcsInfo->u32PinCtls = fVal;
3700
3701 return VINF_SUCCESS;
3702}
3703
3704
3705/**
3706 * Sets up secondary processor-based VM-execution controls in the VMCS.
3707 *
3708 * @returns VBox status code.
3709 * @param pVCpu The cross context virtual CPU structure.
3710 * @param pVmcsInfo The VMCS info. object.
3711 */
3712static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3713{
3714 PVM pVM = pVCpu->CTX_SUFF(pVM);
3715 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3716 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3717
3718 /* WBINVD causes a VM-exit. */
3719 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3720 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3721
3722 /* Enable EPT (aka nested-paging). */
3723 if (pVM->hm.s.fNestedPaging)
3724 fVal |= VMX_PROC_CTLS2_EPT;
3725
3726 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3727 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3728 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3729 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3730 fVal |= VMX_PROC_CTLS2_INVPCID;
3731
3732 /* Enable VPID. */
3733 if (pVM->hm.s.vmx.fVpid)
3734 fVal |= VMX_PROC_CTLS2_VPID;
3735
3736 /* Enable unrestricted guest execution. */
3737 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3738 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3739
3740#if 0
3741 if (pVM->hm.s.fVirtApicRegs)
3742 {
3743 /* Enable APIC-register virtualization. */
3744 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3745 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3746
3747 /* Enable virtual-interrupt delivery. */
3748 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3749 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3750 }
3751#endif
3752
3753 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3754 where the TPR shadow resides. */
3755 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3756 * done dynamically. */
3757 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3758 {
3759 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3760 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3761 AssertRCReturn(rc, rc);
3762 }
3763
3764 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3765 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3766 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3767 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3768 fVal |= VMX_PROC_CTLS2_RDTSCP;
3769
3770 /* Enable Pause-Loop exiting. */
3771 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3772 && pVM->hm.s.vmx.cPleGapTicks
3773 && pVM->hm.s.vmx.cPleWindowTicks)
3774 {
3775 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3776
3777 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3778 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3779 AssertRCReturn(rc, rc);
3780 }
3781
3782 if ((fVal & fZap) != fVal)
3783 {
3784 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3785 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3786 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3787 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3788 }
3789
3790 /* Commit it to the VMCS and update our cache. */
3791 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3792 AssertRCReturn(rc, rc);
3793 pVmcsInfo->u32ProcCtls2 = fVal;
3794
3795 return VINF_SUCCESS;
3796}
3797
3798
3799/**
3800 * Sets up processor-based VM-execution controls in the VMCS.
3801 *
3802 * @returns VBox status code.
3803 * @param pVCpu The cross context virtual CPU structure.
3804 * @param pVmcsInfo The VMCS info. object.
3805 */
3806static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3807{
3808 PVM pVM = pVCpu->CTX_SUFF(pVM);
3809
3810 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3811 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3812
3813 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3814 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3815 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3816 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3817 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3818 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3819 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3820
3821 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3822 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3823 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3824 {
3825 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3826 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3827 }
3828
3829 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3830 if (!pVM->hm.s.fNestedPaging)
3831 {
3832 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3833 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3834 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3835 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3836 }
3837
3838 /* Use TPR shadowing if supported by the CPU. */
3839 if ( PDMHasApic(pVM)
3840 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3841 {
3842 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3843 /* CR8 writes cause a VM-exit based on TPR threshold. */
3844 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3845 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3846 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3847 AssertRCReturn(rc, rc);
3848 }
3849 else
3850 {
3851 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3852 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3853 if (pVM->hm.s.fAllow64BitGuests)
3854 {
3855 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3856 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3857 }
3858 }
3859
3860 /* Use MSR-bitmaps if supported by the CPU. */
3861 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3862 {
3863 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3864 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3865 AssertRCReturn(rc, rc);
3866 }
3867
3868 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3869 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3870 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3871
3872 if ((fVal & fZap) != fVal)
3873 {
3874 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3875 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3876 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3877 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3878 }
3879
3880 /* Commit it to the VMCS and update our cache. */
3881 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3882 AssertRCReturn(rc, rc);
3883 pVmcsInfo->u32ProcCtls = fVal;
3884
3885 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3886 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3887 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3888
3889 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3890 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3891 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3892
3893 /* Sanity check, should not really happen. */
3894 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3895 { /* likely */ }
3896 else
3897 {
3898 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3899 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3900 }
3901
3902 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3903 return VINF_SUCCESS;
3904}
3905
3906
3907/**
3908 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3909 * Processor-based VM-execution) control fields in the VMCS.
3910 *
3911 * @returns VBox status code.
3912 * @param pVCpu The cross context virtual CPU structure.
3913 * @param pVmcsInfo The VMCS info. object.
3914 */
3915static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3916{
3917#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3918 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3919 {
3920 int rc = hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3921 rc |= hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3922 if (RT_SUCCESS(rc))
3923 { /* likely */ }
3924 else
3925 {
3926 LogRelFunc(("Failed to setup VMREAD/VMWRITE bitmap addresses. rc=%Rrc\n", rc));
3927 return rc;
3928 }
3929 }
3930#endif
3931
3932 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3933 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3934 if (RT_SUCCESS(rc))
3935 {
3936 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3937 if (RT_SUCCESS(rc))
3938 {
3939 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3940 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3941 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3942 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3943 if (RT_SUCCESS(rc))
3944 {
3945 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3946 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3947 return VINF_SUCCESS;
3948 }
3949 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3950 }
3951 else
3952 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3953 }
3954 else
3955 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3956 return rc;
3957}
3958
3959
3960/**
3961 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3962 *
3963 * We shall setup those exception intercepts that don't change during the
3964 * lifetime of the VM here. The rest are done dynamically while loading the
3965 * guest state.
3966 *
3967 * @returns VBox status code.
3968 * @param pVCpu The cross context virtual CPU structure.
3969 * @param pVmcsInfo The VMCS info. object.
3970 */
3971static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3972{
3973 /*
3974 * The following exceptions are always intercepted:
3975 *
3976 * #AC - To prevent the guest from hanging the CPU.
3977 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3978 * recursive #DBs can cause a CPU hang.
3979 * #PF - To sync our shadow page tables when nested-paging is not used.
3980 */
3981 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3982 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3983 | RT_BIT(X86_XCPT_DB)
3984 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3985
3986 /* Commit it to the VMCS. */
3987 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3988 AssertRCReturn(rc, rc);
3989
3990 /* Update our cache of the exception bitmap. */
3991 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3992 return VINF_SUCCESS;
3993}
3994
3995
3996#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3997/**
3998 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3999 *
4000 * @returns VBox status code.
4001 * @param pVCpu The cross context virtual CPU structure.
4002 * @param pVmcsInfo The VMCS info. object.
4003 */
4004static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
4005{
4006 PVM pVM = pVCpu->CTX_SUFF(pVM);
4007 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
4008 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
4009 if (RT_SUCCESS(rc))
4010 {
4011 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
4012 if (RT_SUCCESS(rc))
4013 {
4014 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
4015 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
4016 if (RT_SUCCESS(rc))
4017 return VINF_SUCCESS;
4018 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
4019 }
4020 else
4021 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
4022 }
4023 else
4024 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
4025
4026 return rc;
4027}
4028#endif
4029
4030
4031/**
4032 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
4033 * VMX.
4034 *
4035 * @returns VBox status code.
4036 * @param pVCpu The cross context virtual CPU structure.
4037 * @param pVmcsInfo The VMCS info. object.
4038 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
4039 */
4040static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
4041{
4042 Assert(pVmcsInfo->pvVmcs);
4043 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4044
4045 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
4046 PVM pVM = pVCpu->CTX_SUFF(pVM);
4047 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4048 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
4049
4050 LogFlowFunc(("\n"));
4051
4052 /*
4053 * Initialize the VMCS using VMCLEAR before loading the VMCS.
4054 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
4055 */
4056 int rc = hmR0VmxClearVmcs(pVmcsInfo);
4057 if (RT_SUCCESS(rc))
4058 {
4059 rc = hmR0VmxLoadVmcs(pVmcsInfo);
4060 if (RT_SUCCESS(rc))
4061 {
4062 if (!fIsNstGstVmcs)
4063 {
4064 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
4065 if (RT_SUCCESS(rc))
4066 {
4067 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4068 if (RT_SUCCESS(rc))
4069 {
4070 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4071 if (RT_SUCCESS(rc))
4072 {
4073 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4074 if (RT_SUCCESS(rc))
4075 {
4076#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4077 /*
4078 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4079 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4080 * making it fit for use when VMCS shadowing is later enabled.
4081 */
4082 if (pVmcsInfo->pvShadowVmcs)
4083 {
4084 VMXVMCSREVID VmcsRevId;
4085 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4086 VmcsRevId.n.fIsShadowVmcs = 1;
4087 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4088 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4089 if (RT_SUCCESS(rc))
4090 { /* likely */ }
4091 else
4092 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4093 }
4094#endif
4095 }
4096 else
4097 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
4098 }
4099 else
4100 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4101 }
4102 else
4103 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4104 }
4105 else
4106 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4107 }
4108 else
4109 {
4110#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4111 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4112 if (RT_SUCCESS(rc))
4113 { /* likely */ }
4114 else
4115 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4116#else
4117 AssertFailed();
4118#endif
4119 }
4120 }
4121 else
4122 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4123 }
4124 else
4125 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4126
4127 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4128 if (RT_SUCCESS(rc))
4129 {
4130 rc = hmR0VmxClearVmcs(pVmcsInfo);
4131 if (RT_SUCCESS(rc))
4132 { /* likely */ }
4133 else
4134 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4135 }
4136
4137 /*
4138 * Update the last-error record both for failures and success, so we
4139 * can propagate the status code back to ring-3 for diagnostics.
4140 */
4141 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4142 NOREF(pszVmcs);
4143 return rc;
4144}
4145
4146
4147/**
4148 * Does global VT-x initialization (called during module initialization).
4149 *
4150 * @returns VBox status code.
4151 */
4152VMMR0DECL(int) VMXR0GlobalInit(void)
4153{
4154#ifdef HMVMX_USE_FUNCTION_TABLE
4155 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4156# ifdef VBOX_STRICT
4157 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4158 Assert(g_apfnVMExitHandlers[i]);
4159# endif
4160#endif
4161 return VINF_SUCCESS;
4162}
4163
4164
4165/**
4166 * Does global VT-x termination (called during module termination).
4167 */
4168VMMR0DECL(void) VMXR0GlobalTerm()
4169{
4170 /* Nothing to do currently. */
4171}
4172
4173
4174/**
4175 * Sets up and activates VT-x on the current CPU.
4176 *
4177 * @returns VBox status code.
4178 * @param pHostCpu The HM physical-CPU structure.
4179 * @param pVM The cross context VM structure. Can be
4180 * NULL after a host resume operation.
4181 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4182 * fEnabledByHost is @c true).
4183 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4184 * @a fEnabledByHost is @c true).
4185 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4186 * enable VT-x on the host.
4187 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4188 */
4189VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4190 PCSUPHWVIRTMSRS pHwvirtMsrs)
4191{
4192 AssertPtr(pHostCpu);
4193 AssertPtr(pHwvirtMsrs);
4194 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4195
4196 /* Enable VT-x if it's not already enabled by the host. */
4197 if (!fEnabledByHost)
4198 {
4199 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4200 if (RT_FAILURE(rc))
4201 return rc;
4202 }
4203
4204 /*
4205 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4206 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4207 * invalidated when flushing by VPID.
4208 */
4209 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4210 {
4211 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4212 pHostCpu->fFlushAsidBeforeUse = false;
4213 }
4214 else
4215 pHostCpu->fFlushAsidBeforeUse = true;
4216
4217 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4218 ++pHostCpu->cTlbFlushes;
4219
4220 return VINF_SUCCESS;
4221}
4222
4223
4224/**
4225 * Deactivates VT-x on the current CPU.
4226 *
4227 * @returns VBox status code.
4228 * @param pvCpuPage Pointer to the VMXON region.
4229 * @param HCPhysCpuPage Physical address of the VMXON region.
4230 *
4231 * @remarks This function should never be called when SUPR0EnableVTx() or
4232 * similar was used to enable VT-x on the host.
4233 */
4234VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4235{
4236 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4237
4238 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4239 return hmR0VmxLeaveRootMode();
4240}
4241
4242
4243/**
4244 * Does per-VM VT-x initialization.
4245 *
4246 * @returns VBox status code.
4247 * @param pVM The cross context VM structure.
4248 */
4249VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4250{
4251 AssertPtr(pVM);
4252 LogFlowFunc(("pVM=%p\n", pVM));
4253
4254 int rc = hmR0VmxStructsAlloc(pVM);
4255 if (RT_FAILURE(rc))
4256 {
4257 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4258 return rc;
4259 }
4260
4261 return VINF_SUCCESS;
4262}
4263
4264
4265/**
4266 * Does per-VM VT-x termination.
4267 *
4268 * @returns VBox status code.
4269 * @param pVM The cross context VM structure.
4270 */
4271VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4272{
4273 AssertPtr(pVM);
4274 LogFlowFunc(("pVM=%p\n", pVM));
4275
4276#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4277 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4278 {
4279 Assert(pVM->hm.s.vmx.pvScratch);
4280 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4281 }
4282#endif
4283 hmR0VmxStructsFree(pVM);
4284 return VINF_SUCCESS;
4285}
4286
4287
4288/**
4289 * Sets up the VM for execution using hardware-assisted VMX.
4290 * This function is only called once per-VM during initialization.
4291 *
4292 * @returns VBox status code.
4293 * @param pVM The cross context VM structure.
4294 */
4295VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4296{
4297 AssertPtr(pVM);
4298 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4299
4300 LogFlowFunc(("pVM=%p\n", pVM));
4301
4302 /*
4303 * At least verify if VMX is enabled, since we can't check if we're in
4304 * VMX root mode or not without causing a #GP.
4305 */
4306 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4307 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4308 { /* likely */ }
4309 else
4310 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4311
4312 /*
4313 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4314 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4315 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4316 */
4317 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4318 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4319 || !pVM->hm.s.vmx.pRealModeTSS))
4320 {
4321 LogRelFunc(("Invalid real-on-v86 state.\n"));
4322 return VERR_INTERNAL_ERROR;
4323 }
4324
4325 /* Initialize these always, see hmR3InitFinalizeR0().*/
4326 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4327 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4328
4329 /* Setup the tagged-TLB flush handlers. */
4330 int rc = hmR0VmxSetupTaggedTlb(pVM);
4331 if (RT_FAILURE(rc))
4332 {
4333 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4334 return rc;
4335 }
4336
4337#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4338 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4339 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4340 {
4341 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4342 if (RT_SUCCESS(rc))
4343 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4344 else
4345 {
4346 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4347 return rc;
4348 }
4349 }
4350#endif
4351
4352 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4353 {
4354 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4355 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4356
4357 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4358 if (RT_SUCCESS(rc))
4359 {
4360#if HC_ARCH_BITS == 32
4361 hmR0VmxInitVmcsReadCache(pVCpu);
4362#endif
4363#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4364 if (pVM->cpum.ro.GuestFeatures.fVmx)
4365 {
4366 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4367 if (RT_SUCCESS(rc))
4368 { /* likely */ }
4369 else
4370 {
4371 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4372 return rc;
4373 }
4374 }
4375#endif
4376 }
4377 else
4378 {
4379 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4380 return rc;
4381 }
4382 }
4383
4384 return VINF_SUCCESS;
4385}
4386
4387
4388#if HC_ARCH_BITS == 32
4389# ifdef VBOX_ENABLE_64_BITS_GUESTS
4390/**
4391 * Check if guest state allows safe use of 32-bit switcher again.
4392 *
4393 * Segment bases and protected mode structures must be 32-bit addressable
4394 * because the 32-bit switcher will ignore high dword when writing these VMCS
4395 * fields. See @bugref{8432} for details.
4396 *
4397 * @returns true if safe, false if must continue to use the 64-bit switcher.
4398 * @param pCtx Pointer to the guest-CPU context.
4399 *
4400 * @remarks No-long-jump zone!!!
4401 */
4402static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
4403{
4404 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
4405 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
4406 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4407 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4408 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
4409 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4410 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
4411 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
4412 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4413 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4414
4415 /* All good, bases are 32-bit. */
4416 return true;
4417}
4418# endif /* VBOX_ENABLE_64_BITS_GUESTS */
4419
4420# ifdef VBOX_STRICT
4421static bool hmR0VmxIsValidWriteFieldInCache(uint32_t idxField)
4422{
4423 switch (idxField)
4424 {
4425 case VMX_VMCS_GUEST_RIP:
4426 case VMX_VMCS_GUEST_RSP:
4427 case VMX_VMCS_GUEST_SYSENTER_EIP:
4428 case VMX_VMCS_GUEST_SYSENTER_ESP:
4429 case VMX_VMCS_GUEST_GDTR_BASE:
4430 case VMX_VMCS_GUEST_IDTR_BASE:
4431 case VMX_VMCS_GUEST_CS_BASE:
4432 case VMX_VMCS_GUEST_DS_BASE:
4433 case VMX_VMCS_GUEST_ES_BASE:
4434 case VMX_VMCS_GUEST_FS_BASE:
4435 case VMX_VMCS_GUEST_GS_BASE:
4436 case VMX_VMCS_GUEST_SS_BASE:
4437 case VMX_VMCS_GUEST_LDTR_BASE:
4438 case VMX_VMCS_GUEST_TR_BASE:
4439 case VMX_VMCS_GUEST_CR3:
4440 return true;
4441 }
4442 return false;
4443}
4444
4445static bool hmR0VmxIsValidReadFieldInCache(uint32_t idxField)
4446{
4447 switch (idxField)
4448 {
4449 /* Read-only fields. */
4450 case VMX_VMCS_RO_EXIT_QUALIFICATION:
4451 return true;
4452 }
4453 /* Remaining readable fields should also be writable. */
4454 return hmR0VmxIsValidWriteFieldInCache(idxField);
4455}
4456# endif /* VBOX_STRICT */
4457
4458
4459/**
4460 * Executes the specified handler in 64-bit mode.
4461 *
4462 * @returns VBox status code (no informational status codes).
4463 * @param pVCpu The cross context virtual CPU structure.
4464 * @param enmOp The operation to perform.
4465 * @param cParams Number of parameters.
4466 * @param paParam Array of 32-bit parameters.
4467 */
4468VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
4469{
4470 AssertPtr(pVCpu);
4471 PVM pVM = pVCpu->CTX_SUFF(pVM);
4472 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
4473 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
4474 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
4475 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
4476
4477#ifdef VBOX_STRICT
4478 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
4479 Assert(hmR0VmxIsValidWriteFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
4480
4481 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
4482 Assert(hmR0VmxIsValidReadFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
4483#endif
4484
4485 /* Disable interrupts. */
4486 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
4487
4488#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
4489 RTCPUID idHostCpu = RTMpCpuId();
4490 CPUMR0SetLApic(pVCpu, idHostCpu);
4491#endif
4492
4493 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
4494
4495 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4496 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4497
4498 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
4499 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4500 hmR0VmxClearVmcs(pVmcsInfo);
4501
4502 /* Leave VMX root mode and disable VMX. */
4503 VMXDisable();
4504 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4505
4506 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
4507 CPUMSetHyperEIP(pVCpu, enmOp);
4508 for (int i = (int)cParams - 1; i >= 0; i--)
4509 CPUMPushHyper(pVCpu, paParam[i]);
4510
4511 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
4512
4513 /* Call the switcher. */
4514 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
4515 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
4516
4517 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
4518 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
4519
4520 /* Re-enter VMX root mode. */
4521 int rc2 = VMXEnable(HCPhysCpuPage);
4522 if (RT_FAILURE(rc2))
4523 {
4524 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4525 ASMSetFlags(fOldEFlags);
4526 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
4527 return rc2;
4528 }
4529
4530 /* Restore the VMCS as the current VMCS. */
4531 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
4532 AssertRC(rc2);
4533 Assert(!(ASMGetFlags() & X86_EFL_IF));
4534 ASMSetFlags(fOldEFlags);
4535 return rc;
4536}
4537
4538
4539/**
4540 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
4541 * supporting 64-bit guests.
4542 *
4543 * @returns VBox status code.
4544 * @param fResume Whether to VMLAUNCH or VMRESUME.
4545 * @param pCtx Pointer to the guest-CPU context.
4546 * @param pCache Pointer to the VMCS batch cache.
4547 * @param pVM The cross context VM structure.
4548 * @param pVCpu The cross context virtual CPU structure.
4549 */
4550DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
4551{
4552 NOREF(fResume);
4553
4554 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4555 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4556 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4557
4558#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4559 pCache->uPos = 1;
4560 pCache->interPD = PGMGetInterPaeCR3(pVM);
4561 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
4562#endif
4563
4564#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4565 pCache->TestIn.HCPhysCpuPage = 0;
4566 pCache->TestIn.HCPhysVmcs = 0;
4567 pCache->TestIn.pCache = 0;
4568 pCache->TestOut.HCPhysVmcs = 0;
4569 pCache->TestOut.pCache = 0;
4570 pCache->TestOut.pCtx = 0;
4571 pCache->TestOut.eflags = 0;
4572#else
4573 NOREF(pCache);
4574#endif
4575
4576 uint32_t aParam[10];
4577 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
4578 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
4579 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
4580 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
4581 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
4582 aParam[5] = 0;
4583 aParam[6] = VM_RC_ADDR(pVM, pVM);
4584 aParam[7] = 0;
4585 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
4586 aParam[9] = 0;
4587
4588#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4589 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
4590 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
4591#endif
4592 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
4593
4594#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4595 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
4596 Assert(pCtx->dr[4] == 10);
4597 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
4598#endif
4599
4600#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4601 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
4602 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4603 pVmcsInfo->HCPhysVmcs));
4604 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4605 pCache->TestOut.HCPhysVmcs));
4606 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
4607 pCache->TestOut.pCache));
4608 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
4609 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
4610 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
4611 pCache->TestOut.pCtx));
4612 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
4613#endif
4614 NOREF(pCtx);
4615 return rc;
4616}
4617#endif
4618
4619
4620/**
4621 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4622 * the VMCS.
4623 *
4624 * @returns VBox status code.
4625 */
4626static int hmR0VmxExportHostControlRegs(void)
4627{
4628 RTCCUINTREG uReg = ASMGetCR0();
4629 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
4630 AssertRCReturn(rc, rc);
4631
4632 uReg = ASMGetCR3();
4633 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
4634 AssertRCReturn(rc, rc);
4635
4636 uReg = ASMGetCR4();
4637 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
4638 AssertRCReturn(rc, rc);
4639 return rc;
4640}
4641
4642
4643/**
4644 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4645 * the host-state area in the VMCS.
4646 *
4647 * @returns VBox status code.
4648 * @param pVCpu The cross context virtual CPU structure.
4649 */
4650static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4651{
4652#if HC_ARCH_BITS == 64
4653/**
4654 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4655 * requirements. See hmR0VmxExportHostSegmentRegs().
4656 */
4657# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
4658 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4659 { \
4660 bool fValidSelector = true; \
4661 if ((selValue) & X86_SEL_LDT) \
4662 { \
4663 uint32_t uAttr = ASMGetSegAttr((selValue)); \
4664 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4665 } \
4666 if (fValidSelector) \
4667 { \
4668 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
4669 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
4670 } \
4671 (selValue) = 0; \
4672 }
4673
4674 /*
4675 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4676 * will be messed up. We should -not- save the messed up state without restoring
4677 * the original host-state, see @bugref{7240}.
4678 *
4679 * This apparently can happen (most likely the FPU changes), deal with it rather than
4680 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4681 */
4682 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4683 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4684 {
4685 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4686 pVCpu->idCpu));
4687 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4688 }
4689 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4690#else
4691 RT_NOREF(pVCpu);
4692#endif
4693
4694 /*
4695 * Host DS, ES, FS and GS segment registers.
4696 */
4697#if HC_ARCH_BITS == 64
4698 RTSEL uSelDS = ASMGetDS();
4699 RTSEL uSelES = ASMGetES();
4700 RTSEL uSelFS = ASMGetFS();
4701 RTSEL uSelGS = ASMGetGS();
4702#else
4703 RTSEL uSelDS = 0;
4704 RTSEL uSelES = 0;
4705 RTSEL uSelFS = 0;
4706 RTSEL uSelGS = 0;
4707#endif
4708
4709 /*
4710 * Host CS and SS segment registers.
4711 */
4712 RTSEL uSelCS = ASMGetCS();
4713 RTSEL uSelSS = ASMGetSS();
4714
4715 /*
4716 * Host TR segment register.
4717 */
4718 RTSEL uSelTR = ASMGetTR();
4719
4720#if HC_ARCH_BITS == 64
4721 /*
4722 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4723 * gain VM-entry and restore them before we get preempted.
4724 *
4725 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4726 */
4727 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4728 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4729 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4730 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4731# undef VMXLOCAL_ADJUST_HOST_SEG
4732#endif
4733
4734 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4735 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4736 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4737 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4738 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4739 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4740 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4741 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4742 Assert(uSelCS);
4743 Assert(uSelTR);
4744
4745 /* Write these host selector fields into the host-state area in the VMCS. */
4746 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
4747 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
4748#if HC_ARCH_BITS == 64
4749 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
4750 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
4751 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
4752 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
4753#else
4754 NOREF(uSelDS);
4755 NOREF(uSelES);
4756 NOREF(uSelFS);
4757 NOREF(uSelGS);
4758#endif
4759 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
4760 AssertRCReturn(rc, rc);
4761
4762 /*
4763 * Host GDTR and IDTR.
4764 */
4765 RTGDTR Gdtr;
4766 RTIDTR Idtr;
4767 RT_ZERO(Gdtr);
4768 RT_ZERO(Idtr);
4769 ASMGetGDTR(&Gdtr);
4770 ASMGetIDTR(&Idtr);
4771 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
4772 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
4773 AssertRCReturn(rc, rc);
4774
4775#if HC_ARCH_BITS == 64
4776 /*
4777 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4778 * them to the maximum limit (0xffff) on every VM-exit.
4779 */
4780 if (Gdtr.cbGdt != 0xffff)
4781 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4782
4783 /*
4784 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4785 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4786 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4787 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4788 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4789 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4790 * at 0xffff on hosts where we are sure it won't cause trouble.
4791 */
4792# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4793 if (Idtr.cbIdt < 0x0fff)
4794# else
4795 if (Idtr.cbIdt != 0xffff)
4796# endif
4797 {
4798 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4799 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4800 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4801 }
4802#endif
4803
4804 /*
4805 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4806 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4807 * RPL should be too in most cases.
4808 */
4809 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4810 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4811
4812 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4813#if HC_ARCH_BITS == 64
4814 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4815
4816 /*
4817 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4818 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4819 * restoration if the host has something else. Task switching is not supported in 64-bit
4820 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4821 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4822 *
4823 * [1] See Intel spec. 3.5 "System Descriptor Types".
4824 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4825 */
4826 PVM pVM = pVCpu->CTX_SUFF(pVM);
4827 Assert(pDesc->System.u4Type == 11);
4828 if ( pDesc->System.u16LimitLow != 0x67
4829 || pDesc->System.u4LimitHigh)
4830 {
4831 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4832 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4833 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4834 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4835 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4836 }
4837
4838 /*
4839 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4840 */
4841 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4842 {
4843 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4844 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4845 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4846 {
4847 /* The GDT is read-only but the writable GDT is available. */
4848 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4849 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4850 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4851 AssertRCReturn(rc, rc);
4852 }
4853 }
4854#else
4855 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4856#endif
4857 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4858 AssertRCReturn(rc, rc);
4859
4860 /*
4861 * Host FS base and GS base.
4862 */
4863#if HC_ARCH_BITS == 64
4864 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4865 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4866 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4867 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4868 AssertRCReturn(rc, rc);
4869
4870 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4871 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4872 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4873 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4874 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4875#endif
4876 return VINF_SUCCESS;
4877}
4878
4879
4880/**
4881 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4882 * host-state area of the VMCS.
4883 *
4884 * These MSRs will be automatically restored on the host after every successful
4885 * VM-exit.
4886 *
4887 * @returns VBox status code.
4888 * @param pVCpu The cross context virtual CPU structure.
4889 *
4890 * @remarks No-long-jump zone!!!
4891 */
4892static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4893{
4894 AssertPtr(pVCpu);
4895
4896 /*
4897 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4898 * rather than swapping them on every VM-entry.
4899 */
4900 hmR0VmxLazySaveHostMsrs(pVCpu);
4901
4902 /*
4903 * Host Sysenter MSRs.
4904 */
4905 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4906#if HC_ARCH_BITS == 32
4907 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4908 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4909#else
4910 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4911 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4912#endif
4913 AssertRCReturn(rc, rc);
4914
4915 /*
4916 * Host EFER MSR.
4917 *
4918 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4919 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4920 */
4921 PVM pVM = pVCpu->CTX_SUFF(pVM);
4922 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4923 {
4924 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4925 AssertRCReturn(rc, rc);
4926 }
4927
4928 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4929 * hmR0VmxExportGuestEntryExitCtls(). */
4930
4931 return VINF_SUCCESS;
4932}
4933
4934
4935/**
4936 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4937 *
4938 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4939 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4940 *
4941 * @returns true if we need to load guest EFER, false otherwise.
4942 * @param pVCpu The cross context virtual CPU structure.
4943 *
4944 * @remarks Requires EFER, CR4.
4945 * @remarks No-long-jump zone!!!
4946 */
4947static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4948{
4949#ifdef HMVMX_ALWAYS_SWAP_EFER
4950 RT_NOREF(pVCpu);
4951 return true;
4952#else
4953 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4954#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4955 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4956 if (CPUMIsGuestInLongModeEx(pCtx))
4957 return false;
4958#endif
4959
4960 PVM pVM = pVCpu->CTX_SUFF(pVM);
4961 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4962 uint64_t const u64GuestEfer = pCtx->msrEFER;
4963
4964 /*
4965 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4966 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4967 */
4968 if ( CPUMIsGuestInLongModeEx(pCtx)
4969 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4970 return true;
4971
4972 /*
4973 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4974 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4975 *
4976 * See Intel spec. 4.5 "IA-32e Paging".
4977 * See Intel spec. 4.1.1 "Three Paging Modes".
4978 *
4979 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4980 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4981 */
4982 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4983 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4984 if ( (pCtx->cr4 & X86_CR4_PAE)
4985 && (pCtx->cr0 & X86_CR0_PG)
4986 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4987 {
4988 /* Assert that host is NX capable. */
4989 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4990 return true;
4991 }
4992
4993 return false;
4994#endif
4995}
4996
4997/**
4998 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4999 * VMCS.
5000 *
5001 * This is typically required when the guest changes paging mode.
5002 *
5003 * @returns VBox status code.
5004 * @param pVCpu The cross context virtual CPU structure.
5005 * @param pVmxTransient The VMX-transient structure.
5006 *
5007 * @remarks Requires EFER.
5008 * @remarks No-long-jump zone!!!
5009 */
5010static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5011{
5012 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
5013 {
5014 PVM pVM = pVCpu->CTX_SUFF(pVM);
5015 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5016
5017 /*
5018 * VM-entry controls.
5019 */
5020 {
5021 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5022 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5023
5024 /*
5025 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
5026 * The first VT-x capable CPUs only supported the 1-setting of this bit.
5027 *
5028 * For nested-guests, this is a mandatory VM-entry control. It's also
5029 * required because we do not want to leak host bits to the nested-guest.
5030 */
5031 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
5032
5033 /*
5034 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
5035 *
5036 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
5037 * required to get the nested-guest working with hardware-assisted VMX execution.
5038 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
5039 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
5040 * here rather than while merging the guest VMCS controls.
5041 */
5042 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
5043 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
5044 else
5045 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
5046
5047 /*
5048 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
5049 *
5050 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
5051 * regardless of whether the nested-guest VMCS specifies it because we are free to
5052 * load whatever MSRs we require and we do not need to modify the guest visible copy
5053 * of the VM-entry MSR load area.
5054 */
5055 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5056 && hmR0VmxShouldSwapEferMsr(pVCpu))
5057 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
5058 else
5059 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
5060
5061 /*
5062 * The following should -not- be set (since we're not in SMM mode):
5063 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
5064 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
5065 */
5066
5067 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
5068 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
5069
5070 if ((fVal & fZap) == fVal)
5071 { /* likely */ }
5072 else
5073 {
5074 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5075 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
5076 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5077 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5078 }
5079
5080 /* Commit it to the VMCS. */
5081 if (pVmcsInfo->u32EntryCtls != fVal)
5082 {
5083 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5084 AssertRCReturn(rc, rc);
5085 pVmcsInfo->u32EntryCtls = fVal;
5086 }
5087 }
5088
5089 /*
5090 * VM-exit controls.
5091 */
5092 {
5093 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5094 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5095
5096 /*
5097 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5098 * supported the 1-setting of this bit.
5099 *
5100 * For nested-guests, we set the "save debug controls" as the converse
5101 * "load debug controls" is mandatory for nested-guests anyway.
5102 */
5103 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5104
5105 /*
5106 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5107 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5108 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5109 * hmR0VmxExportHostMsrs().
5110 *
5111 * For nested-guests, we always set this bit as we do not support 32-bit
5112 * hosts.
5113 */
5114#if HC_ARCH_BITS == 64
5115 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5116#else
5117 Assert(!pVmxTransient->fIsNestedGuest);
5118 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
5119 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
5120 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
5121 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
5122 {
5123 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
5124 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5125 }
5126 else
5127 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
5128#endif
5129
5130 /*
5131 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5132 *
5133 * For nested-guests, we should use the "save IA32_EFER" control if we also
5134 * used the "load IA32_EFER" control while exporting VM-entry controls.
5135 */
5136 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5137 && hmR0VmxShouldSwapEferMsr(pVCpu))
5138 {
5139 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5140 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5141 }
5142
5143 /*
5144 * Enable saving of the VMX-preemption timer value on VM-exit.
5145 * For nested-guests, currently not exposed/used.
5146 */
5147 if ( pVM->hm.s.vmx.fUsePreemptTimer
5148 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5149 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5150
5151 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5152 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5153
5154 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5155 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5156 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5157
5158 if ((fVal & fZap) == fVal)
5159 { /* likely */ }
5160 else
5161 {
5162 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5163 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5164 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5165 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5166 }
5167
5168 /* Commit it to the VMCS. */
5169 if (pVmcsInfo->u32ExitCtls != fVal)
5170 {
5171 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5172 AssertRCReturn(rc, rc);
5173 pVmcsInfo->u32ExitCtls = fVal;
5174 }
5175 }
5176
5177 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5178 }
5179 return VINF_SUCCESS;
5180}
5181
5182
5183/**
5184 * Sets the TPR threshold in the VMCS.
5185 *
5186 * @returns VBox status code.
5187 * @param pVCpu The cross context virtual CPU structure.
5188 * @param pVmcsInfo The VMCS info. object.
5189 * @param u32TprThreshold The TPR threshold (task-priority class only).
5190 */
5191DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5192{
5193 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5194 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5195 RT_NOREF2(pVCpu, pVmcsInfo);
5196 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5197}
5198
5199
5200/**
5201 * Exports the guest APIC TPR state into the VMCS.
5202 *
5203 * @returns VBox status code.
5204 * @param pVCpu The cross context virtual CPU structure.
5205 * @param pVmxTransient The VMX-transient structure.
5206 *
5207 * @remarks No-long-jump zone!!!
5208 */
5209static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5210{
5211 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5212 {
5213 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5214
5215 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5216 if (!pVmxTransient->fIsNestedGuest)
5217 {
5218 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5219 && APICIsEnabled(pVCpu))
5220 {
5221 /*
5222 * Setup TPR shadowing.
5223 */
5224 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5225 {
5226 bool fPendingIntr = false;
5227 uint8_t u8Tpr = 0;
5228 uint8_t u8PendingIntr = 0;
5229 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5230 AssertRCReturn(rc, rc);
5231
5232 /*
5233 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5234 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5235 * priority of the pending interrupt so we can deliver the interrupt. If there
5236 * are no interrupts pending, set threshold to 0 to not cause any
5237 * TPR-below-threshold VM-exits.
5238 */
5239 uint32_t u32TprThreshold = 0;
5240 if (fPendingIntr)
5241 {
5242 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5243 (which is the Task-Priority Class). */
5244 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5245 const uint8_t u8TprPriority = u8Tpr >> 4;
5246 if (u8PendingPriority <= u8TprPriority)
5247 u32TprThreshold = u8PendingPriority;
5248 }
5249
5250 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
5251 AssertRCReturn(rc, rc);
5252 }
5253 }
5254 }
5255 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5256 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5257 }
5258 return VINF_SUCCESS;
5259}
5260
5261
5262/**
5263 * Gets the guest interruptibility-state.
5264 *
5265 * @returns Guest's interruptibility-state.
5266 * @param pVCpu The cross context virtual CPU structure.
5267 * @param pVmxTransient The VMX-transient structure.
5268 *
5269 * @remarks No-long-jump zone!!!
5270 */
5271static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5272{
5273 /*
5274 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5275 */
5276 uint32_t fIntrState = 0;
5277 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5278 {
5279 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
5280 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
5281
5282 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5283 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5284 {
5285 if (pCtx->eflags.Bits.u1IF)
5286 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5287 else
5288 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5289 }
5290 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5291 {
5292 /*
5293 * We can clear the inhibit force flag as even if we go back to the recompiler
5294 * without executing guest code in VT-x, the flag's condition to be cleared is
5295 * met and thus the cleared state is correct.
5296 */
5297 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5298 }
5299 }
5300
5301 /*
5302 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
5303 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
5304 * setting this would block host-NMIs and IRET will not clear the blocking.
5305 *
5306 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
5307 *
5308 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
5309 */
5310 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5311 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
5312 && CPUMIsGuestNmiBlocking(pVCpu))
5313 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5314
5315 return fIntrState;
5316}
5317
5318
5319/**
5320 * Exports the exception intercepts required for guest execution in the VMCS.
5321 *
5322 * @returns VBox status code.
5323 * @param pVCpu The cross context virtual CPU structure.
5324 * @param pVmxTransient The VMX-transient structure.
5325 *
5326 * @remarks No-long-jump zone!!!
5327 */
5328static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5329{
5330 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5331 {
5332 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5333 if ( !pVmxTransient->fIsNestedGuest
5334 && pVCpu->hm.s.fGIMTrapXcptUD)
5335 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5336 else
5337 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5338
5339 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5340 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5341 }
5342 return VINF_SUCCESS;
5343}
5344
5345
5346/**
5347 * Exports the guest's RIP into the guest-state area in the VMCS.
5348 *
5349 * @returns VBox status code.
5350 * @param pVCpu The cross context virtual CPU structure.
5351 *
5352 * @remarks No-long-jump zone!!!
5353 */
5354static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
5355{
5356 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5357 {
5358 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5359
5360 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5361 AssertRCReturn(rc, rc);
5362
5363 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5364 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5365 }
5366 return VINF_SUCCESS;
5367}
5368
5369
5370/**
5371 * Exports the guest's RSP into the guest-state area in the VMCS.
5372 *
5373 * @returns VBox status code.
5374 * @param pVCpu The cross context virtual CPU structure.
5375 *
5376 * @remarks No-long-jump zone!!!
5377 */
5378static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
5379{
5380 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5381 {
5382 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5383
5384 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5385 AssertRCReturn(rc, rc);
5386
5387 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5388 }
5389 return VINF_SUCCESS;
5390}
5391
5392
5393/**
5394 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5395 *
5396 * @returns VBox status code.
5397 * @param pVCpu The cross context virtual CPU structure.
5398 * @param pVmxTransient The VMX-transient structure.
5399 *
5400 * @remarks No-long-jump zone!!!
5401 */
5402static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5403{
5404 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5405 {
5406 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5407
5408 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5409 Let us assert it as such and use 32-bit VMWRITE. */
5410 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5411 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5412 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5413 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5414
5415 /*
5416 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5417 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5418 * can run the real-mode guest code under Virtual 8086 mode.
5419 */
5420 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5421 if (pVmcsInfo->RealMode.fRealOnV86Active)
5422 {
5423 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5424 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5425 Assert(!pVmxTransient->fIsNestedGuest);
5426 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5427 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5428 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5429 }
5430
5431 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5432 AssertRCReturn(rc, rc);
5433
5434 /*
5435 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5436 *
5437 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5438 * through the hypervisor debugger using EFLAGS.TF.
5439 */
5440 if ( !pVmxTransient->fIsNestedGuest
5441 && !pVCpu->hm.s.fSingleInstruction
5442 && fEFlags.Bits.u1TF)
5443 {
5444 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5445 * premature trips to ring-3 esp since IEM does not yet handle it. */
5446 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5447 AssertRCReturn(rc, rc);
5448 }
5449 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
5450 * nested-guest VMCS. */
5451
5452 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5453 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5454 }
5455 return VINF_SUCCESS;
5456}
5457
5458
5459#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5460/**
5461 * Copies the nested-guest VMCS to the shadow VMCS.
5462 *
5463 * @returns VBox status code.
5464 * @param pVCpu The cross context virtual CPU structure.
5465 * @param pVmcsInfo The VMCS info. object.
5466 *
5467 * @remarks No-long-jump zone!!!
5468 */
5469static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5470{
5471 PVM pVM = pVCpu->CTX_SUFF(pVM);
5472 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5473
5474 /*
5475 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5476 * current VMCS, as we may try saving guest lazy MSRs.
5477 *
5478 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5479 * calling the import VMCS code which is currently performing the guest MSR reads
5480 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5481 * and the rest of the VMX leave session machinery.
5482 */
5483 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5484
5485 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5486 if (RT_SUCCESS(rc))
5487 {
5488 /*
5489 * Copy all guest read/write VMCS fields.
5490 *
5491 * We don't check for VMWRITE 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 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5501 VMXWriteVmcs64(uVmcsField, u64Val);
5502 }
5503
5504 /*
5505 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5506 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5507 */
5508 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5509 {
5510 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5511 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5512 {
5513 uint64_t u64Val;
5514 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5515 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5516 VMXWriteVmcs64(uVmcsField, u64Val);
5517 }
5518 }
5519
5520 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5521 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5522 }
5523
5524 ASMSetFlags(fEFlags);
5525 return rc;
5526}
5527
5528
5529/**
5530 * Copies the shadow VMCS to the nested-guest VMCS.
5531 *
5532 * @returns VBox status code.
5533 * @param pVCpu The cross context virtual CPU structure.
5534 * @param pVmcsInfo The VMCS info. object.
5535 *
5536 * @remarks Called with interrupts disabled.
5537 */
5538static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5539{
5540 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5541 PVM pVM = pVCpu->CTX_SUFF(pVM);
5542 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5543
5544 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5545 if (RT_SUCCESS(rc))
5546 {
5547 /*
5548 * Copy guest read/write fields from the shadow VMCS.
5549 * Guest read-only fields cannot be modified, so no need to copy them.
5550 *
5551 * We don't check for VMREAD failures here for performance reasons and
5552 * because they are not expected to fail, barring irrecoverable conditions
5553 * like hardware errors.
5554 */
5555 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5556 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5557 {
5558 uint64_t u64Val;
5559 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5560 VMXReadVmcs64(uVmcsField, &u64Val);
5561 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5562 }
5563
5564 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5565 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5566 }
5567 return rc;
5568}
5569
5570
5571/**
5572 * Enables VMCS shadowing for the given VMCS info. object.
5573 *
5574 * @param pVCpu The cross context virtual CPU structure.
5575 * @param pVmcsInfo The VMCS info. object.
5576 *
5577 * @remarks No-long-jump zone!!!
5578 */
5579static void hmR0VmxEnableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5580{
5581 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5582
5583 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5584 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5585 {
5586 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5587 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5588 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5589 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs);
5590 AssertRC(rc);
5591
5592 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5593 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5594 Log4Func(("Enabled\n"));
5595 }
5596}
5597
5598
5599/**
5600 * Disables VMCS shadowing for the given VMCS info. object.
5601 *
5602 * @param pVCpu The cross context virtual CPU structure.
5603 * @param pVmcsInfo The VMCS info. object.
5604 *
5605 * @remarks No-long-jump zone!!!
5606 */
5607static void hmR0VmxDisableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5608{
5609 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5610
5611 /*
5612 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5613 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5614 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5615 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5616 *
5617 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5618 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5619 */
5620 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5621 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5622 {
5623 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5624 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5625 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
5626 AssertRC(rc);
5627
5628 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5629 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5630 Log4Func(("Disabled\n"));
5631 }
5632}
5633#endif
5634
5635
5636/**
5637 * Exports the guest hardware-virtualization state.
5638 *
5639 * @returns VBox status code.
5640 * @param pVCpu The cross context virtual CPU structure.
5641 * @param pVmxTransient The VMX-transient structure.
5642 *
5643 * @remarks No-long-jump zone!!!
5644 */
5645static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5646{
5647 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5648 {
5649#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5650 /*
5651 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5652 * VMCS shadowing.
5653 */
5654 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5655 {
5656 /*
5657 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5658 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5659 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5660 *
5661 * We check for VMX root mode here in case the guest executes VMXOFF without
5662 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5663 * not clear the current VMCS pointer.
5664 */
5665 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5666 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5667 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5668 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5669 {
5670 /* Paranoia. */
5671 Assert(!pVmxTransient->fIsNestedGuest);
5672
5673 /*
5674 * For performance reasons, also check if the guest hypervisor's current VMCS
5675 * was newly loaded or modified before copying it to the shadow VMCS.
5676 */
5677 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5678 {
5679 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5680 AssertRCReturn(rc, rc);
5681 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5682 }
5683 hmR0VmxEnableVmcsShadowing(pVCpu, pVmcsInfo);
5684 }
5685 else
5686 hmR0VmxDisableVmcsShadowing(pVCpu, pVmcsInfo);
5687 }
5688#else
5689 NOREF(pVmxTransient);
5690#endif
5691 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5692 }
5693 return VINF_SUCCESS;
5694}
5695
5696
5697/**
5698 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5699 *
5700 * The guest FPU state is always pre-loaded hence we don't need to bother about
5701 * sharing FPU related CR0 bits between the guest and host.
5702 *
5703 * @returns VBox status code.
5704 * @param pVCpu The cross context virtual CPU structure.
5705 * @param pVmxTransient The VMX-transient structure.
5706 *
5707 * @remarks No-long-jump zone!!!
5708 */
5709static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5710{
5711 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5712 {
5713 PVM pVM = pVCpu->CTX_SUFF(pVM);
5714 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5715
5716 /*
5717 * Figure out fixed CR0 bits in VMX operation.
5718 */
5719 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5720 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5721 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5722 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5723 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5724 else
5725 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5726
5727 if (!pVmxTransient->fIsNestedGuest)
5728 {
5729 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5730 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5731 uint64_t const u64ShadowCr0 = u64GuestCr0;
5732 Assert(!RT_HI_U32(u64GuestCr0));
5733
5734 /*
5735 * Setup VT-x's view of the guest CR0.
5736 */
5737 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5738 if (pVM->hm.s.fNestedPaging)
5739 {
5740 if (CPUMIsGuestPagingEnabled(pVCpu))
5741 {
5742 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5743 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5744 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5745 }
5746 else
5747 {
5748 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5749 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5750 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5751 }
5752
5753 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5754 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5755 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5756 }
5757 else
5758 {
5759 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5760 u64GuestCr0 |= X86_CR0_WP;
5761 }
5762
5763 /*
5764 * Guest FPU bits.
5765 *
5766 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5767 * using CR0.TS.
5768 *
5769 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5770 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5771 */
5772 u64GuestCr0 |= X86_CR0_NE;
5773
5774 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5775 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5776
5777 /*
5778 * Update exception intercepts.
5779 */
5780 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5781 if (pVmcsInfo->RealMode.fRealOnV86Active)
5782 {
5783 Assert(PDMVmmDevHeapIsEnabled(pVM));
5784 Assert(pVM->hm.s.vmx.pRealModeTSS);
5785 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5786 }
5787 else
5788 {
5789 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5790 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5791 if (fInterceptMF)
5792 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5793 }
5794
5795 /* Additional intercepts for debugging, define these yourself explicitly. */
5796#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5797 uXcptBitmap |= 0
5798 | RT_BIT(X86_XCPT_BP)
5799 | RT_BIT(X86_XCPT_DE)
5800 | RT_BIT(X86_XCPT_NM)
5801 | RT_BIT(X86_XCPT_TS)
5802 | RT_BIT(X86_XCPT_UD)
5803 | RT_BIT(X86_XCPT_NP)
5804 | RT_BIT(X86_XCPT_SS)
5805 | RT_BIT(X86_XCPT_GP)
5806 | RT_BIT(X86_XCPT_PF)
5807 | RT_BIT(X86_XCPT_MF)
5808 ;
5809#elif defined(HMVMX_ALWAYS_TRAP_PF)
5810 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5811#endif
5812 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5813 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5814 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5815
5816 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5817 u64GuestCr0 |= fSetCr0;
5818 u64GuestCr0 &= fZapCr0;
5819 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5820
5821 /* Commit the CR0 and related fields to the guest VMCS. */
5822 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
5823 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5824 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5825 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5826 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5827 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5828 AssertRCReturn(rc, rc);
5829
5830 /* Update our caches. */
5831 pVmcsInfo->u32ProcCtls = uProcCtls;
5832 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5833
5834 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5835 }
5836 else
5837 {
5838 /*
5839 * With nested-guests, we may have extended the guest/host mask here since we
5840 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5841 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5842 * originally supplied. We must copy those bits from the nested-guest CR0 into
5843 * the nested-guest CR0 read-shadow.
5844 */
5845 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5846 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5847 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5848 Assert(!RT_HI_U32(u64GuestCr0));
5849 Assert(u64GuestCr0 & X86_CR0_NE);
5850
5851 /*
5852 * Apply the hardware specified fixed CR0 bits and enable caching.
5853 * Note! We could be altering our VMX emulation's fixed bits. We thus
5854 * need to re-apply them while importing CR0.
5855 */
5856 u64GuestCr0 |= fSetCr0;
5857 u64GuestCr0 &= fZapCr0;
5858 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5859
5860 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5861 /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
5862 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0);
5863 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5864 AssertRCReturn(rc, rc);
5865
5866 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5867 }
5868
5869 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5870 }
5871
5872 return VINF_SUCCESS;
5873}
5874
5875
5876/**
5877 * Exports the guest control registers (CR3, CR4) into the guest-state area
5878 * in the VMCS.
5879 *
5880 * @returns VBox strict status code.
5881 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5882 * without unrestricted guest access and the VMMDev is not presently
5883 * mapped (e.g. EFI32).
5884 *
5885 * @param pVCpu The cross context virtual CPU structure.
5886 * @param pVmxTransient The VMX-transient structure.
5887 *
5888 * @remarks No-long-jump zone!!!
5889 */
5890static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5891{
5892 int rc = VINF_SUCCESS;
5893 PVM pVM = pVCpu->CTX_SUFF(pVM);
5894
5895 /*
5896 * Guest CR2.
5897 * It's always loaded in the assembler code. Nothing to do here.
5898 */
5899
5900 /*
5901 * Guest CR3.
5902 */
5903 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5904 {
5905 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5906
5907 RTGCPHYS GCPhysGuestCr3 = NIL_RTGCPHYS;
5908 if (pVM->hm.s.fNestedPaging)
5909 {
5910 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5911 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5912
5913 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5914 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5915 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5916 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5917
5918 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5919 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5920 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5921
5922 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5923 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5924 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5925 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5926 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5927 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5928 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5929
5930 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5931 AssertRCReturn(rc, rc);
5932
5933 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5934 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5935 || CPUMIsGuestPagingEnabledEx(pCtx))
5936 {
5937 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5938 if (CPUMIsGuestInPAEModeEx(pCtx))
5939 {
5940 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5941 AssertRCReturn(rc, rc);
5942 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
5943 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
5944 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
5945 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
5946 AssertRCReturn(rc, rc);
5947 }
5948
5949 /*
5950 * The guest's view of its CR3 is unblemished with nested paging when the
5951 * guest is using paging or we have unrestricted guest execution to handle
5952 * the guest when it's not using paging.
5953 */
5954 GCPhysGuestCr3 = pCtx->cr3;
5955 }
5956 else
5957 {
5958 /*
5959 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5960 * thinks it accesses physical memory directly, we use our identity-mapped
5961 * page table to map guest-linear to guest-physical addresses. EPT takes care
5962 * of translating it to host-physical addresses.
5963 */
5964 RTGCPHYS GCPhys;
5965 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5966
5967 /* We obtain it here every time as the guest could have relocated this PCI region. */
5968 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5969 if (RT_SUCCESS(rc))
5970 { /* likely */ }
5971 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5972 {
5973 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5974 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5975 }
5976 else
5977 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5978
5979 GCPhysGuestCr3 = GCPhys;
5980 }
5981
5982 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCr3));
5983 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCr3);
5984 AssertRCReturn(rc, rc);
5985 }
5986 else
5987 {
5988 /* Non-nested paging case, just use the hypervisor's CR3. */
5989 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5990
5991 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCr3));
5992 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5993 AssertRCReturn(rc, rc);
5994 }
5995
5996 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5997 }
5998
5999 /*
6000 * Guest CR4.
6001 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
6002 */
6003 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
6004 {
6005 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6006 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6007
6008 /*
6009 * Figure out fixed CR4 bits in VMX operation.
6010 */
6011 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
6012 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
6013 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
6014
6015 /*
6016 * With nested-guests, we may have extended the guest/host mask here (since we
6017 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
6018 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
6019 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
6020 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
6021 */
6022 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
6023 uint64_t u64GuestCr4 = pCtx->cr4;
6024 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
6025 ? pCtx->cr4
6026 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
6027 Assert(!RT_HI_U32(u64GuestCr4));
6028
6029 /*
6030 * Setup VT-x's view of the guest CR4.
6031 *
6032 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
6033 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
6034 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
6035 *
6036 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
6037 */
6038 if (pVmcsInfo->RealMode.fRealOnV86Active)
6039 {
6040 Assert(pVM->hm.s.vmx.pRealModeTSS);
6041 Assert(PDMVmmDevHeapIsEnabled(pVM));
6042 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
6043 }
6044
6045 if (pVM->hm.s.fNestedPaging)
6046 {
6047 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
6048 && !pVM->hm.s.vmx.fUnrestrictedGuest)
6049 {
6050 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
6051 u64GuestCr4 |= X86_CR4_PSE;
6052 /* Our identity mapping is a 32-bit page directory. */
6053 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6054 }
6055 /* else use guest CR4.*/
6056 }
6057 else
6058 {
6059 Assert(!pVmxTransient->fIsNestedGuest);
6060
6061 /*
6062 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
6063 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
6064 */
6065 switch (pVCpu->hm.s.enmShadowMode)
6066 {
6067 case PGMMODE_REAL: /* Real-mode. */
6068 case PGMMODE_PROTECTED: /* Protected mode without paging. */
6069 case PGMMODE_32_BIT: /* 32-bit paging. */
6070 {
6071 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6072 break;
6073 }
6074
6075 case PGMMODE_PAE: /* PAE paging. */
6076 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6077 {
6078 u64GuestCr4 |= X86_CR4_PAE;
6079 break;
6080 }
6081
6082 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6083 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6084#ifdef VBOX_ENABLE_64_BITS_GUESTS
6085 break;
6086#endif
6087 default:
6088 AssertFailed();
6089 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6090 }
6091 }
6092
6093 /*
6094 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
6095 * Note! For nested-guests, we could be altering our VMX emulation's
6096 * fixed bits. We thus need to re-apply them while importing CR4.
6097 */
6098 u64GuestCr4 |= fSetCr4;
6099 u64GuestCr4 &= fZapCr4;
6100
6101 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6102 /** @todo Fix to 64-bit when we drop 32-bit. */
6103 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4);
6104 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
6105 AssertRCReturn(rc, rc);
6106
6107 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6108 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6109
6110 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6111
6112 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6113 }
6114 return rc;
6115}
6116
6117
6118/**
6119 * Exports the guest debug registers into the guest-state area in the VMCS.
6120 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6121 *
6122 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6123 *
6124 * @returns VBox status code.
6125 * @param pVCpu The cross context virtual CPU structure.
6126 * @param pVmxTransient The VMX-transient structure.
6127 *
6128 * @remarks No-long-jump zone!!!
6129 */
6130static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6131{
6132 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6133
6134 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6135 * stepping. */
6136 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6137 if (pVmxTransient->fIsNestedGuest)
6138 {
6139 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6140 AssertRCReturn(rc, rc);
6141
6142 /* Always intercept Mov DRx accesses for the nested-guest for now. */
6143 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6144 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
6145 AssertRCReturn(rc, rc);
6146 return VINF_SUCCESS;
6147 }
6148
6149#ifdef VBOX_STRICT
6150 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6151 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6152 {
6153 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6154 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6155 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6156 }
6157#endif
6158
6159 bool fSteppingDB = false;
6160 bool fInterceptMovDRx = false;
6161 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6162 if (pVCpu->hm.s.fSingleInstruction)
6163 {
6164 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6165 PVM pVM = pVCpu->CTX_SUFF(pVM);
6166 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6167 {
6168 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6169 Assert(fSteppingDB == false);
6170 }
6171 else
6172 {
6173 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6174 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6175 pVCpu->hm.s.fClearTrapFlag = true;
6176 fSteppingDB = true;
6177 }
6178 }
6179
6180 uint32_t u32GuestDr7;
6181 if ( fSteppingDB
6182 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6183 {
6184 /*
6185 * Use the combined guest and host DRx values found in the hypervisor register set
6186 * because the hypervisor debugger has breakpoints active or someone is single stepping
6187 * on the host side without a monitor trap flag.
6188 *
6189 * Note! DBGF expects a clean DR6 state before executing guest code.
6190 */
6191#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6192 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6193 && !CPUMIsHyperDebugStateActivePending(pVCpu))
6194 {
6195 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6196 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
6197 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
6198 }
6199 else
6200#endif
6201 if (!CPUMIsHyperDebugStateActive(pVCpu))
6202 {
6203 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6204 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6205 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6206 }
6207
6208 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6209 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
6210 pVCpu->hm.s.fUsingHyperDR7 = true;
6211 fInterceptMovDRx = true;
6212 }
6213 else
6214 {
6215 /*
6216 * If the guest has enabled debug registers, we need to load them prior to
6217 * executing guest code so they'll trigger at the right time.
6218 */
6219 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6220 {
6221#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6222 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6223 && !CPUMIsGuestDebugStateActivePending(pVCpu))
6224 {
6225 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6226 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
6227 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
6228 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6229 }
6230 else
6231#endif
6232 if (!CPUMIsGuestDebugStateActive(pVCpu))
6233 {
6234 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6235 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6236 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6237 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6238 }
6239 Assert(!fInterceptMovDRx);
6240 }
6241 /*
6242 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6243 * must intercept #DB in order to maintain a correct DR6 guest value, and
6244 * because we need to intercept it to prevent nested #DBs from hanging the
6245 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6246 */
6247#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6248 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
6249 && !CPUMIsGuestDebugStateActive(pVCpu))
6250#else
6251 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6252#endif
6253 {
6254 fInterceptMovDRx = true;
6255 }
6256
6257 /* Update DR7 with the actual guest value. */
6258 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6259 pVCpu->hm.s.fUsingHyperDR7 = false;
6260 }
6261
6262 if (fInterceptMovDRx)
6263 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6264 else
6265 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6266
6267 /*
6268 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6269 * monitor-trap flag and update our cache.
6270 */
6271 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6272 {
6273 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6274 AssertRCReturn(rc2, rc2);
6275 pVmcsInfo->u32ProcCtls = uProcCtls;
6276 }
6277
6278 /*
6279 * Update guest DR7.
6280 */
6281 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
6282 AssertRCReturn(rc, rc);
6283
6284 /*
6285 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6286 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6287 *
6288 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6289 */
6290 if (fSteppingDB)
6291 {
6292 Assert(pVCpu->hm.s.fSingleInstruction);
6293 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6294
6295 uint32_t fIntrState = 0;
6296 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6297 AssertRCReturn(rc, rc);
6298
6299 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6300 {
6301 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6302 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6303 AssertRCReturn(rc, rc);
6304 }
6305 }
6306
6307 return VINF_SUCCESS;
6308}
6309
6310
6311#ifdef VBOX_STRICT
6312/**
6313 * Strict function to validate segment registers.
6314 *
6315 * @param pVCpu The cross context virtual CPU structure.
6316 * @param pVmcsInfo The VMCS info. object.
6317 *
6318 * @remarks Will import guest CR0 on strict builds during validation of
6319 * segments.
6320 */
6321static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
6322{
6323 /*
6324 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6325 *
6326 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6327 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6328 * unusable bit and doesn't change the guest-context value.
6329 */
6330 PVM pVM = pVCpu->CTX_SUFF(pVM);
6331 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6332 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6333 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6334 && ( !CPUMIsGuestInRealModeEx(pCtx)
6335 && !CPUMIsGuestInV86ModeEx(pCtx)))
6336 {
6337 /* Protected mode checks */
6338 /* CS */
6339 Assert(pCtx->cs.Attr.n.u1Present);
6340 Assert(!(pCtx->cs.Attr.u & 0xf00));
6341 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6342 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6343 || !(pCtx->cs.Attr.n.u1Granularity));
6344 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6345 || (pCtx->cs.Attr.n.u1Granularity));
6346 /* CS cannot be loaded with NULL in protected mode. */
6347 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6348 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6349 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6350 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6351 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6352 else
6353 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6354 /* SS */
6355 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6356 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6357 if ( !(pCtx->cr0 & X86_CR0_PE)
6358 || pCtx->cs.Attr.n.u4Type == 3)
6359 {
6360 Assert(!pCtx->ss.Attr.n.u2Dpl);
6361 }
6362 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6363 {
6364 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6365 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6366 Assert(pCtx->ss.Attr.n.u1Present);
6367 Assert(!(pCtx->ss.Attr.u & 0xf00));
6368 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6369 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6370 || !(pCtx->ss.Attr.n.u1Granularity));
6371 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6372 || (pCtx->ss.Attr.n.u1Granularity));
6373 }
6374 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6375 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6376 {
6377 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6378 Assert(pCtx->ds.Attr.n.u1Present);
6379 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6380 Assert(!(pCtx->ds.Attr.u & 0xf00));
6381 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6382 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6383 || !(pCtx->ds.Attr.n.u1Granularity));
6384 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6385 || (pCtx->ds.Attr.n.u1Granularity));
6386 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6387 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6388 }
6389 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6390 {
6391 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6392 Assert(pCtx->es.Attr.n.u1Present);
6393 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6394 Assert(!(pCtx->es.Attr.u & 0xf00));
6395 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6396 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6397 || !(pCtx->es.Attr.n.u1Granularity));
6398 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6399 || (pCtx->es.Attr.n.u1Granularity));
6400 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6401 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6402 }
6403 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6404 {
6405 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6406 Assert(pCtx->fs.Attr.n.u1Present);
6407 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6408 Assert(!(pCtx->fs.Attr.u & 0xf00));
6409 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6410 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6411 || !(pCtx->fs.Attr.n.u1Granularity));
6412 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6413 || (pCtx->fs.Attr.n.u1Granularity));
6414 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6415 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6416 }
6417 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6418 {
6419 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6420 Assert(pCtx->gs.Attr.n.u1Present);
6421 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6422 Assert(!(pCtx->gs.Attr.u & 0xf00));
6423 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6424 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6425 || !(pCtx->gs.Attr.n.u1Granularity));
6426 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6427 || (pCtx->gs.Attr.n.u1Granularity));
6428 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6429 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6430 }
6431 /* 64-bit capable CPUs. */
6432# if HC_ARCH_BITS == 64
6433 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6434 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6435 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6436 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6437# endif
6438 }
6439 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6440 || ( CPUMIsGuestInRealModeEx(pCtx)
6441 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6442 {
6443 /* Real and v86 mode checks. */
6444 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6445 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6446 if (pVmcsInfo->RealMode.fRealOnV86Active)
6447 {
6448 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6449 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6450 }
6451 else
6452 {
6453 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6454 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6455 }
6456
6457 /* CS */
6458 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6459 Assert(pCtx->cs.u32Limit == 0xffff);
6460 Assert(u32CSAttr == 0xf3);
6461 /* SS */
6462 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6463 Assert(pCtx->ss.u32Limit == 0xffff);
6464 Assert(u32SSAttr == 0xf3);
6465 /* DS */
6466 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6467 Assert(pCtx->ds.u32Limit == 0xffff);
6468 Assert(u32DSAttr == 0xf3);
6469 /* ES */
6470 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6471 Assert(pCtx->es.u32Limit == 0xffff);
6472 Assert(u32ESAttr == 0xf3);
6473 /* FS */
6474 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6475 Assert(pCtx->fs.u32Limit == 0xffff);
6476 Assert(u32FSAttr == 0xf3);
6477 /* GS */
6478 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6479 Assert(pCtx->gs.u32Limit == 0xffff);
6480 Assert(u32GSAttr == 0xf3);
6481 /* 64-bit capable CPUs. */
6482# if HC_ARCH_BITS == 64
6483 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6484 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6485 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6486 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6487# endif
6488 }
6489}
6490#endif /* VBOX_STRICT */
6491
6492
6493/**
6494 * Exports a guest segment register into the guest-state area in the VMCS.
6495 *
6496 * @returns VBox status code.
6497 * @param pVCpu The cross context virtual CPU structure.
6498 * @param pVmcsInfo The VMCS info. object.
6499 * @param iSegReg The segment register number (X86_SREG_XXX).
6500 * @param pSelReg Pointer to the segment selector.
6501 *
6502 * @remarks No-long-jump zone!!!
6503 */
6504static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6505{
6506 Assert(iSegReg < X86_SREG_COUNT);
6507 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6508 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6509 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6510 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6511
6512 uint32_t u32Access = pSelReg->Attr.u;
6513 if (pVmcsInfo->RealMode.fRealOnV86Active)
6514 {
6515 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6516 u32Access = 0xf3;
6517 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6518 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6519 RT_NOREF_PV(pVCpu);
6520 }
6521 else
6522 {
6523 /*
6524 * The way to differentiate between whether this is really a null selector or was just
6525 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6526 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6527 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6528 * NULL selectors loaded in protected-mode have their attribute as 0.
6529 */
6530 if (!u32Access)
6531 u32Access = X86DESCATTR_UNUSABLE;
6532 }
6533
6534 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6535 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6536 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6537
6538 /*
6539 * Commit it to the VMCS.
6540 */
6541 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
6542 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
6543 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
6544 rc |= VMXWriteVmcs32(idxAttr, u32Access);
6545 AssertRCReturn(rc, rc);
6546 return rc;
6547}
6548
6549
6550/**
6551 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6552 * area in the VMCS.
6553 *
6554 * @returns VBox status code.
6555 * @param pVCpu The cross context virtual CPU structure.
6556 * @param pVmxTransient The VMX-transient structure.
6557 *
6558 * @remarks Will import guest CR0 on strict builds during validation of
6559 * segments.
6560 * @remarks No-long-jump zone!!!
6561 */
6562static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6563{
6564 int rc = VERR_INTERNAL_ERROR_5;
6565 PVM pVM = pVCpu->CTX_SUFF(pVM);
6566 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6567 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6568
6569 /*
6570 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6571 */
6572 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6573 {
6574#ifdef VBOX_WITH_REM
6575 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6576 {
6577 Assert(!pVmxTransient->fIsNestedGuest);
6578 Assert(pVM->hm.s.vmx.pRealModeTSS);
6579 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6580 if ( pVmcsInfo->fWasInRealMode
6581 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6582 {
6583 /*
6584 * Notify the recompiler must flush its code-cache as the guest -may-
6585 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6586 */
6587 REMFlushTBs(pVM);
6588 Log4Func(("Switch to protected mode detected!\n"));
6589 pVmcsInfo->fWasInRealMode = false;
6590 }
6591 }
6592#endif
6593 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6594 {
6595 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6596 if (pVmcsInfo->RealMode.fRealOnV86Active)
6597 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6598 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6599 AssertRCReturn(rc, rc);
6600 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6601 }
6602
6603 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6604 {
6605 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6606 if (pVmcsInfo->RealMode.fRealOnV86Active)
6607 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6608 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6609 AssertRCReturn(rc, rc);
6610 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6611 }
6612
6613 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6614 {
6615 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6616 if (pVmcsInfo->RealMode.fRealOnV86Active)
6617 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6618 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6619 AssertRCReturn(rc, rc);
6620 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6621 }
6622
6623 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6624 {
6625 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6626 if (pVmcsInfo->RealMode.fRealOnV86Active)
6627 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6628 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6629 AssertRCReturn(rc, rc);
6630 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6631 }
6632
6633 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6634 {
6635 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6636 if (pVmcsInfo->RealMode.fRealOnV86Active)
6637 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6638 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6639 AssertRCReturn(rc, rc);
6640 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6641 }
6642
6643 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6644 {
6645 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6646 if (pVmcsInfo->RealMode.fRealOnV86Active)
6647 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6648 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6649 AssertRCReturn(rc, rc);
6650 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6651 }
6652
6653#ifdef VBOX_STRICT
6654 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6655#endif
6656 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6657 pCtx->cs.Attr.u));
6658 }
6659
6660 /*
6661 * Guest TR.
6662 */
6663 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6664 {
6665 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6666
6667 /*
6668 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6669 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6670 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6671 */
6672 uint16_t u16Sel;
6673 uint32_t u32Limit;
6674 uint64_t u64Base;
6675 uint32_t u32AccessRights;
6676 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6677 {
6678 u16Sel = pCtx->tr.Sel;
6679 u32Limit = pCtx->tr.u32Limit;
6680 u64Base = pCtx->tr.u64Base;
6681 u32AccessRights = pCtx->tr.Attr.u;
6682 }
6683 else
6684 {
6685 Assert(!pVmxTransient->fIsNestedGuest);
6686 Assert(pVM->hm.s.vmx.pRealModeTSS);
6687 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6688
6689 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6690 RTGCPHYS GCPhys;
6691 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6692 AssertRCReturn(rc, rc);
6693
6694 X86DESCATTR DescAttr;
6695 DescAttr.u = 0;
6696 DescAttr.n.u1Present = 1;
6697 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6698
6699 u16Sel = 0;
6700 u32Limit = HM_VTX_TSS_SIZE;
6701 u64Base = GCPhys;
6702 u32AccessRights = DescAttr.u;
6703 }
6704
6705 /* Validate. */
6706 Assert(!(u16Sel & RT_BIT(2)));
6707 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6708 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6709 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6710 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6711 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6712 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6713 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6714 Assert( (u32Limit & 0xfff) == 0xfff
6715 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6716 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6717 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6718
6719 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
6720 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
6721 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
6722 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
6723 AssertRCReturn(rc, rc);
6724
6725 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6726 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6727 }
6728
6729 /*
6730 * Guest GDTR.
6731 */
6732 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6733 {
6734 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6735
6736 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
6737 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
6738 AssertRCReturn(rc, rc);
6739
6740 /* Validate. */
6741 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6742
6743 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6744 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6745 }
6746
6747 /*
6748 * Guest LDTR.
6749 */
6750 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6751 {
6752 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6753
6754 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6755 uint32_t u32Access;
6756 if ( !pVmxTransient->fIsNestedGuest
6757 && !pCtx->ldtr.Attr.u)
6758 u32Access = X86DESCATTR_UNUSABLE;
6759 else
6760 u32Access = pCtx->ldtr.Attr.u;
6761
6762 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
6763 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
6764 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
6765 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
6766 AssertRCReturn(rc, rc);
6767
6768 /* Validate. */
6769 if (!(u32Access & X86DESCATTR_UNUSABLE))
6770 {
6771 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6772 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6773 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6774 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6775 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6776 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6777 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6778 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6779 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6780 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6781 }
6782
6783 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6784 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6785 }
6786
6787 /*
6788 * Guest IDTR.
6789 */
6790 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6791 {
6792 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6793
6794 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
6795 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
6796 AssertRCReturn(rc, rc);
6797
6798 /* Validate. */
6799 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6800
6801 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6802 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6803 }
6804
6805 return VINF_SUCCESS;
6806}
6807
6808
6809/**
6810 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6811 * areas.
6812 *
6813 * These MSRs will automatically be loaded to the host CPU on every successful
6814 * VM-entry and stored from the host CPU on every successful VM-exit.
6815 *
6816 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6817 * actual host MSR values are not- updated here for performance reasons. See
6818 * hmR0VmxExportHostMsrs().
6819 *
6820 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6821 *
6822 * @returns VBox status code.
6823 * @param pVCpu The cross context virtual CPU structure.
6824 * @param pVmxTransient The VMX-transient structure.
6825 *
6826 * @remarks No-long-jump zone!!!
6827 */
6828static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6829{
6830 AssertPtr(pVCpu);
6831 AssertPtr(pVmxTransient);
6832
6833 PVM pVM = pVCpu->CTX_SUFF(pVM);
6834 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6835
6836 /*
6837 * MSRs that we use the auto-load/store MSR area in the VMCS.
6838 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
6839 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
6840 *
6841 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6842 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6843 * emulation, nothing to do here.
6844 */
6845 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6846 {
6847 if ( !pVmxTransient->fIsNestedGuest
6848 && pVM->hm.s.fAllow64BitGuests)
6849 {
6850#if HC_ARCH_BITS == 32
6851 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
6852 Assert(!pVmxTransient->fIsNestedGuest);
6853
6854 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
6855 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
6856 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
6857 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
6858 AssertRCReturn(rc, rc);
6859#endif
6860 }
6861 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6862 }
6863
6864 /*
6865 * Guest Sysenter MSRs.
6866 */
6867 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6868 {
6869 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6870
6871 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6872 {
6873 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6874 AssertRCReturn(rc, rc);
6875 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6876 }
6877
6878 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6879 {
6880 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6881 AssertRCReturn(rc, rc);
6882 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6883 }
6884
6885 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6886 {
6887 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6888 AssertRCReturn(rc, rc);
6889 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6890 }
6891 }
6892
6893 /*
6894 * Guest/host EFER MSR.
6895 */
6896 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6897 {
6898 /* Whether we are using the VMCS to swap the EFER MSR must have been
6899 determined earlier while exporting VM-entry/VM-exit controls. */
6900 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6901 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6902
6903 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6904 {
6905 /*
6906 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6907 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6908 */
6909 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6910 {
6911 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6912 AssertRCReturn(rc, rc);
6913 }
6914 else
6915 {
6916 /*
6917 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6918 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6919 */
6920 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6921 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6922 AssertRCReturn(rc, rc);
6923 }
6924 }
6925 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6926 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6927
6928 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6929 }
6930
6931 /*
6932 * Other MSRs.
6933 * Speculation Control (R/W).
6934 */
6935 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6936 {
6937 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6938 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6939 {
6940 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6941 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6942 AssertRCReturn(rc, rc);
6943 }
6944 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6945 }
6946
6947 return VINF_SUCCESS;
6948}
6949
6950
6951/**
6952 * Selects up the appropriate function to run guest code.
6953 *
6954 * @returns VBox status code.
6955 * @param pVCpu The cross context virtual CPU structure.
6956 * @param pVmxTransient The VMX-transient structure.
6957 *
6958 * @remarks No-long-jump zone!!!
6959 */
6960static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6961{
6962 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6963 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6964
6965 if (CPUMIsGuestInLongModeEx(pCtx))
6966 {
6967#ifndef VBOX_ENABLE_64_BITS_GUESTS
6968 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6969#endif
6970 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6971#if HC_ARCH_BITS == 32
6972 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
6973 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
6974 {
6975#ifdef VBOX_STRICT
6976 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6977 {
6978 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6979 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6980 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6981 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6982 ("fCtxChanged=%#RX64\n", fCtxChanged));
6983 }
6984#endif
6985 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
6986
6987 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
6988 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
6989 pVmcsInfo->fSwitchedTo64on32 = true;
6990 Log4Func(("Selected 64-bit switcher\n"));
6991 }
6992#else
6993 /* 64-bit host. */
6994 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6995#endif
6996 }
6997 else
6998 {
6999 /* Guest is not in long mode, use the 32-bit handler. */
7000#if HC_ARCH_BITS == 32
7001 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
7002 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
7003 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
7004 {
7005# ifdef VBOX_STRICT
7006 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
7007 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
7008 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
7009 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
7010 ("fCtxChanged=%#RX64\n", fCtxChanged));
7011# endif
7012 }
7013# ifdef VBOX_ENABLE_64_BITS_GUESTS
7014 /*
7015 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
7016 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
7017 * switcher flag now because we know the guest is in a sane state where it's safe
7018 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
7019 * the much faster 32-bit switcher again.
7020 */
7021 if (!pVmcsInfo->fSwitchedTo64on32)
7022 {
7023 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
7024 Log4Func(("Selected 32-bit switcher\n"));
7025 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7026 }
7027 else
7028 {
7029 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
7030 if ( pVmcsInfo->RealMode.fRealOnV86Active
7031 || hmR0VmxIs32BitSwitcherSafe(pCtx))
7032 {
7033 pVmcsInfo->fSwitchedTo64on32 = false;
7034 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7035 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
7036 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
7037 | HM_CHANGED_HOST_CONTEXT);
7038 Log4Func(("Selected 32-bit switcher (safe)\n"));
7039 }
7040 }
7041# else
7042 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7043# endif
7044#else
7045 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
7046#endif
7047 }
7048 Assert(pVmcsInfo->pfnStartVM);
7049 return VINF_SUCCESS;
7050}
7051
7052
7053/**
7054 * Wrapper for running the guest code in VT-x.
7055 *
7056 * @returns VBox status code, no informational status codes.
7057 * @param pVCpu The cross context virtual CPU structure.
7058 * @param pVmxTransient The VMX-transient structure.
7059 *
7060 * @remarks No-long-jump zone!!!
7061 */
7062DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
7063{
7064 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
7065 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7066 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
7067
7068 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
7069
7070 /*
7071 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
7072 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
7073 * callee-saved and thus the need for this XMM wrapper.
7074 *
7075 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
7076 */
7077 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
7078 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
7079 PVM pVM = pVCpu->CTX_SUFF(pVM);
7080#ifdef VBOX_WITH_KERNEL_USING_XMM
7081 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
7082#else
7083 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
7084#endif
7085 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
7086 return rc;
7087}
7088
7089
7090/**
7091 * Reports world-switch error and dumps some useful debug info.
7092 *
7093 * @param pVCpu The cross context virtual CPU structure.
7094 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
7095 * @param pVmxTransient The VMX-transient structure (only
7096 * exitReason updated).
7097 */
7098static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
7099{
7100 Assert(pVCpu);
7101 Assert(pVmxTransient);
7102 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
7103
7104 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
7105 switch (rcVMRun)
7106 {
7107 case VERR_VMX_INVALID_VMXON_PTR:
7108 AssertFailed();
7109 break;
7110 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
7111 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
7112 {
7113 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
7114 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
7115 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
7116 AssertRC(rc);
7117
7118 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
7119 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
7120 Cannot do it here as we may have been long preempted. */
7121
7122#ifdef VBOX_STRICT
7123 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7124 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
7125 pVmxTransient->uExitReason));
7126 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
7127 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
7128 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
7129 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
7130 else
7131 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
7132 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
7133 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
7134
7135 /* VMX control bits. */
7136 uint32_t u32Val;
7137 uint64_t u64Val;
7138 RTHCUINTREG uHCReg;
7139 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
7140 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
7141 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
7142 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
7143 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
7144 {
7145 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
7146 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
7147 }
7148 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
7149 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
7150 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
7151 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
7152 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
7153 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
7154 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
7155 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
7156 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
7157 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
7158 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
7159 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
7160 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
7161 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
7162 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
7163 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
7164 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7165 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
7166 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7167 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
7168 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
7169 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
7170 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
7171 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
7172 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
7173 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
7174 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
7175 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
7176 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
7177 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7178 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
7179 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
7180 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
7181 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7182 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7183 {
7184 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
7185 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
7186 }
7187
7188 /* Guest bits. */
7189 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
7190 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
7191 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
7192 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
7193 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
7194 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
7195 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
7196 {
7197 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
7198 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
7199 }
7200
7201 /* Host bits. */
7202 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
7203 Log4(("Host CR0 %#RHr\n", uHCReg));
7204 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
7205 Log4(("Host CR3 %#RHr\n", uHCReg));
7206 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
7207 Log4(("Host CR4 %#RHr\n", uHCReg));
7208
7209 RTGDTR HostGdtr;
7210 PCX86DESCHC pDesc;
7211 ASMGetGDTR(&HostGdtr);
7212 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
7213 Log4(("Host CS %#08x\n", u32Val));
7214 if (u32Val < HostGdtr.cbGdt)
7215 {
7216 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7217 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
7218 }
7219
7220 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
7221 Log4(("Host DS %#08x\n", u32Val));
7222 if (u32Val < HostGdtr.cbGdt)
7223 {
7224 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7225 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
7226 }
7227
7228 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
7229 Log4(("Host ES %#08x\n", u32Val));
7230 if (u32Val < HostGdtr.cbGdt)
7231 {
7232 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7233 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
7234 }
7235
7236 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
7237 Log4(("Host FS %#08x\n", u32Val));
7238 if (u32Val < HostGdtr.cbGdt)
7239 {
7240 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7241 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
7242 }
7243
7244 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
7245 Log4(("Host GS %#08x\n", u32Val));
7246 if (u32Val < HostGdtr.cbGdt)
7247 {
7248 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7249 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
7250 }
7251
7252 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
7253 Log4(("Host SS %#08x\n", u32Val));
7254 if (u32Val < HostGdtr.cbGdt)
7255 {
7256 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7257 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
7258 }
7259
7260 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
7261 Log4(("Host TR %#08x\n", u32Val));
7262 if (u32Val < HostGdtr.cbGdt)
7263 {
7264 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7265 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
7266 }
7267
7268 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
7269 Log4(("Host TR Base %#RHv\n", uHCReg));
7270 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
7271 Log4(("Host GDTR Base %#RHv\n", uHCReg));
7272 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
7273 Log4(("Host IDTR Base %#RHv\n", uHCReg));
7274 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
7275 Log4(("Host SYSENTER CS %#08x\n", u32Val));
7276 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
7277 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
7278 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
7279 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
7280 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
7281 Log4(("Host RSP %#RHv\n", uHCReg));
7282 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
7283 Log4(("Host RIP %#RHv\n", uHCReg));
7284# if HC_ARCH_BITS == 64
7285 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7286 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7287 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7288 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7289 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7290 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7291# endif
7292#endif /* VBOX_STRICT */
7293 break;
7294 }
7295
7296 default:
7297 /* Impossible */
7298 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7299 break;
7300 }
7301}
7302
7303
7304#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
7305# ifndef VMX_USE_CACHED_VMCS_ACCESSES
7306# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
7307# endif
7308
7309/**
7310 * Initialize the VMCS-Read cache.
7311 *
7312 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
7313 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
7314 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
7315 * (those that have a 32-bit FULL & HIGH part).
7316 *
7317 * @param pVCpu The cross context virtual CPU structure.
7318 */
7319static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
7320{
7321#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
7322 do { \
7323 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
7324 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
7325 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
7326 ++cReadFields; \
7327 } while (0)
7328
7329 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7330 uint32_t cReadFields = 0;
7331
7332 /*
7333 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
7334 * and serve to indicate exceptions to the rules.
7335 */
7336
7337 /* Guest-natural selector base fields. */
7338#if 0
7339 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
7340 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
7341 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
7342#endif
7343 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
7344 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
7345 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
7346 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
7347 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
7348 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
7349 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
7350 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
7351 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
7352 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
7353 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
7354 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
7355#if 0
7356 /* Unused natural width guest-state fields. */
7357 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
7358 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
7359#endif
7360 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
7361 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
7362
7363 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
7364 these 64-bit fields (using "FULL" and "HIGH" fields). */
7365#if 0
7366 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
7367 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
7368 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
7369 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
7370 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
7371 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
7372 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
7373 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
7374 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
7375#endif
7376
7377 /* Natural width guest-state fields. */
7378 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
7379 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
7380
7381 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7382 {
7383 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
7384 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
7385 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
7386 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
7387 }
7388 else
7389 {
7390 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
7391 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
7392 }
7393
7394#undef VMXLOCAL_INIT_READ_CACHE_FIELD
7395}
7396
7397
7398/**
7399 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
7400 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
7401 * darwin, running 64-bit guests).
7402 *
7403 * @returns VBox status code.
7404 * @param pVCpu The cross context virtual CPU structure.
7405 * @param idxField The VMCS field encoding.
7406 * @param u64Val 16, 32 or 64-bit value.
7407 */
7408VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7409{
7410 AssertPtr(pVCpu);
7411 int rc;
7412 switch (idxField)
7413 {
7414 /*
7415 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
7416 */
7417 /* 64-bit Control fields. */
7418 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
7419 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
7420 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
7421 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
7422 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
7423 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
7424 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
7425 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
7426 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
7427 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
7428 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
7429 case VMX_VMCS64_CTRL_EPTP_FULL:
7430 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
7431 /* 64-bit Guest-state fields. */
7432 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
7433 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
7434 case VMX_VMCS64_GUEST_PAT_FULL:
7435 case VMX_VMCS64_GUEST_EFER_FULL:
7436 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
7437 case VMX_VMCS64_GUEST_PDPTE0_FULL:
7438 case VMX_VMCS64_GUEST_PDPTE1_FULL:
7439 case VMX_VMCS64_GUEST_PDPTE2_FULL:
7440 case VMX_VMCS64_GUEST_PDPTE3_FULL:
7441 /* 64-bit Host-state fields. */
7442 case VMX_VMCS64_HOST_PAT_FULL:
7443 case VMX_VMCS64_HOST_EFER_FULL:
7444 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
7445 {
7446 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7447 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
7448 break;
7449 }
7450
7451 /*
7452 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
7453 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
7454 */
7455 /* Natural-width Guest-state fields. */
7456 case VMX_VMCS_GUEST_CR3:
7457 case VMX_VMCS_GUEST_ES_BASE:
7458 case VMX_VMCS_GUEST_CS_BASE:
7459 case VMX_VMCS_GUEST_SS_BASE:
7460 case VMX_VMCS_GUEST_DS_BASE:
7461 case VMX_VMCS_GUEST_FS_BASE:
7462 case VMX_VMCS_GUEST_GS_BASE:
7463 case VMX_VMCS_GUEST_LDTR_BASE:
7464 case VMX_VMCS_GUEST_TR_BASE:
7465 case VMX_VMCS_GUEST_GDTR_BASE:
7466 case VMX_VMCS_GUEST_IDTR_BASE:
7467 case VMX_VMCS_GUEST_RSP:
7468 case VMX_VMCS_GUEST_RIP:
7469 case VMX_VMCS_GUEST_SYSENTER_ESP:
7470 case VMX_VMCS_GUEST_SYSENTER_EIP:
7471 {
7472 if (!(RT_HI_U32(u64Val)))
7473 {
7474 /* If this field is 64-bit, VT-x will zero out the top bits. */
7475 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7476 }
7477 else
7478 {
7479 /* Assert that only the 32->64 switcher case should ever come here. */
7480 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
7481 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
7482 }
7483 break;
7484 }
7485
7486 default:
7487 {
7488 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
7489 pVCpu->hm.s.u32HMError = idxField;
7490 rc = VERR_INVALID_PARAMETER;
7491 break;
7492 }
7493 }
7494 AssertRCReturn(rc, rc);
7495 return rc;
7496}
7497
7498
7499/**
7500 * Queue up a VMWRITE by using the VMCS write cache.
7501 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
7502 *
7503 * @param pVCpu The cross context virtual CPU structure.
7504 * @param idxField The VMCS field encoding.
7505 * @param u64Val 16, 32 or 64-bit value.
7506 */
7507VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7508{
7509 AssertPtr(pVCpu);
7510 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7511
7512 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
7513 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
7514
7515 /* Make sure there are no duplicates. */
7516 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
7517 {
7518 if (pCache->Write.aField[i] == idxField)
7519 {
7520 pCache->Write.aFieldVal[i] = u64Val;
7521 return VINF_SUCCESS;
7522 }
7523 }
7524
7525 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
7526 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
7527 pCache->Write.cValidEntries++;
7528 return VINF_SUCCESS;
7529}
7530#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
7531
7532
7533/**
7534 * Sets up the usage of TSC-offsetting and updates the VMCS.
7535 *
7536 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7537 * VMX-preemption timer.
7538 *
7539 * @returns VBox status code.
7540 * @param pVCpu The cross context virtual CPU structure.
7541 * @param pVmxTransient The VMX-transient structure.
7542 *
7543 * @remarks No-long-jump zone!!!
7544 */
7545static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
7546{
7547 bool fOffsettedTsc;
7548 bool fParavirtTsc;
7549 uint64_t uTscOffset;
7550 PVM pVM = pVCpu->CTX_SUFF(pVM);
7551 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7552
7553 if (pVM->hm.s.vmx.fUsePreemptTimer)
7554 {
7555 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7556
7557 /* Make sure the returned values have sane upper and lower boundaries. */
7558 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7559 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7560 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7561 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7562
7563 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7564 * preemption timers here. We probably need to clamp the preemption timer,
7565 * after converting the timer value to the host. */
7566 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7567 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7568 AssertRC(rc);
7569 }
7570 else
7571 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7572
7573 if (fParavirtTsc)
7574 {
7575 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7576 information before every VM-entry, hence disable it for performance sake. */
7577#if 0
7578 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7579 AssertRC(rc);
7580#endif
7581 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7582 }
7583
7584 if ( fOffsettedTsc
7585 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7586 {
7587 if (pVmxTransient->fIsNestedGuest)
7588 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7589 hmR0VmxSetTscOffsetVmcs(pVCpu, pVmcsInfo, uTscOffset);
7590 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7591 }
7592 else
7593 {
7594 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7595 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7596 }
7597}
7598
7599
7600/**
7601 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7602 * VM-exit interruption info type.
7603 *
7604 * @returns The IEM exception flags.
7605 * @param uVector The event vector.
7606 * @param uVmxEventType The VMX event type.
7607 *
7608 * @remarks This function currently only constructs flags required for
7609 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7610 * and CR2 aspects of an exception are not included).
7611 */
7612static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7613{
7614 uint32_t fIemXcptFlags;
7615 switch (uVmxEventType)
7616 {
7617 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7618 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7619 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7620 break;
7621
7622 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7623 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7624 break;
7625
7626 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7627 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7628 break;
7629
7630 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7631 {
7632 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7633 if (uVector == X86_XCPT_BP)
7634 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7635 else if (uVector == X86_XCPT_OF)
7636 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7637 else
7638 {
7639 fIemXcptFlags = 0;
7640 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7641 }
7642 break;
7643 }
7644
7645 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7646 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7647 break;
7648
7649 default:
7650 fIemXcptFlags = 0;
7651 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7652 break;
7653 }
7654 return fIemXcptFlags;
7655}
7656
7657
7658/**
7659 * Sets an event as a pending event to be injected into the guest.
7660 *
7661 * @param pVCpu The cross context virtual CPU structure.
7662 * @param u32IntInfo The VM-entry interruption-information field.
7663 * @param cbInstr The VM-entry instruction length in bytes (for software
7664 * interrupts, exceptions and privileged software
7665 * exceptions).
7666 * @param u32ErrCode The VM-entry exception error code.
7667 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7668 * page-fault.
7669 */
7670DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7671 RTGCUINTPTR GCPtrFaultAddress)
7672{
7673 Assert(!pVCpu->hm.s.Event.fPending);
7674 pVCpu->hm.s.Event.fPending = true;
7675 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7676 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7677 pVCpu->hm.s.Event.cbInstr = cbInstr;
7678 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7679}
7680
7681
7682/**
7683 * Sets an external interrupt as pending-for-injection into the VM.
7684 *
7685 * @param pVCpu The cross context virtual CPU structure.
7686 * @param u8Interrupt The external interrupt vector.
7687 */
7688DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
7689{
7690 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7691 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7692 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7693 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7694 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7695}
7696
7697
7698/**
7699 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7700 *
7701 * @param pVCpu The cross context virtual CPU structure.
7702 */
7703DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
7704{
7705 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7706 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7707 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7708 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7709 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7710}
7711
7712
7713/**
7714 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7715 *
7716 * @param pVCpu The cross context virtual CPU structure.
7717 */
7718DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
7719{
7720 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7721 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7722 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7723 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7724 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7725}
7726
7727
7728/**
7729 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7730 *
7731 * @param pVCpu The cross context virtual CPU structure.
7732 */
7733DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
7734{
7735 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7736 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7737 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7738 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7739 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7740}
7741
7742
7743/**
7744 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7745 *
7746 * @param pVCpu The cross context virtual CPU structure.
7747 */
7748DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
7749{
7750 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7751 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7752 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7753 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7754 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7755}
7756
7757
7758#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7759/**
7760 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7761 *
7762 * @param pVCpu The cross context virtual CPU structure.
7763 * @param u32ErrCode The error code for the general-protection exception.
7764 */
7765DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
7766{
7767 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7768 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7769 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7770 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7771 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7772}
7773
7774
7775/**
7776 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7777 *
7778 * @param pVCpu The cross context virtual CPU structure.
7779 * @param u32ErrCode The error code for the stack exception.
7780 */
7781DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
7782{
7783 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7784 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7785 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7786 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7787 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7788}
7789#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7790
7791
7792/**
7793 * Fixes up attributes for the specified segment register.
7794 *
7795 * @param pVCpu The cross context virtual CPU structure.
7796 * @param pSelReg The segment register that needs fixing.
7797 * @param idxSel The VMCS field for the corresponding segment register.
7798 */
7799static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7800{
7801 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7802
7803 /*
7804 * If VT-x marks the segment as unusable, most other bits remain undefined:
7805 * - For CS the L, D and G bits have meaning.
7806 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7807 * - For the remaining data segments no bits are defined.
7808 *
7809 * The present bit and the unusable bit has been observed to be set at the
7810 * same time (the selector was supposed to be invalid as we started executing
7811 * a V8086 interrupt in ring-0).
7812 *
7813 * What should be important for the rest of the VBox code, is that the P bit is
7814 * cleared. Some of the other VBox code recognizes the unusable bit, but
7815 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7816 * safe side here, we'll strip off P and other bits we don't care about. If
7817 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7818 *
7819 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7820 */
7821#ifdef VBOX_STRICT
7822 uint32_t const uAttr = pSelReg->Attr.u;
7823#endif
7824
7825 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7826 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7827 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7828
7829#ifdef VBOX_STRICT
7830 VMMRZCallRing3Disable(pVCpu);
7831 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7832# ifdef DEBUG_bird
7833 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7834 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7835 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7836# endif
7837 VMMRZCallRing3Enable(pVCpu);
7838 NOREF(uAttr);
7839#endif
7840 RT_NOREF2(pVCpu, idxSel);
7841}
7842
7843
7844/**
7845 * Imports a guest segment register from the current VMCS into the guest-CPU
7846 * context.
7847 *
7848 * @returns VBox status code.
7849 * @param pVCpu The cross context virtual CPU structure.
7850 * @param iSegReg The segment register number (X86_SREG_XXX).
7851 *
7852 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7853 * do not log!
7854 */
7855static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7856{
7857 Assert(iSegReg < X86_SREG_COUNT);
7858
7859 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7860 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7861 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7862#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7863 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7864#else
7865 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7866#endif
7867 uint64_t u64Base;
7868 uint32_t u32Sel, u32Limit, u32Attr;
7869 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7870 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7871 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7872 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7873 if (RT_SUCCESS(rc))
7874 {
7875 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7876 pSelReg->Sel = u32Sel;
7877 pSelReg->ValidSel = u32Sel;
7878 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7879 pSelReg->u32Limit = u32Limit;
7880 pSelReg->u64Base = u64Base;
7881 pSelReg->Attr.u = u32Attr;
7882 if (u32Attr & X86DESCATTR_UNUSABLE)
7883 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7884 }
7885 return rc;
7886}
7887
7888
7889/**
7890 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7891 *
7892 * @returns VBox status code.
7893 * @param pVCpu The cross context virtual CPU structure.
7894 *
7895 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7896 * do not log!
7897 */
7898static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7899{
7900 uint64_t u64Base;
7901 uint32_t u32Sel, u32Limit, u32Attr;
7902 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7903 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7904 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7905 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7906 if (RT_SUCCESS(rc))
7907 {
7908 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7909 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7910 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7911 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7912 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7913 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7914 if (u32Attr & X86DESCATTR_UNUSABLE)
7915 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7916 }
7917 return rc;
7918}
7919
7920
7921/**
7922 * Imports the guest TR from the current VMCS into the guest-CPU context.
7923 *
7924 * @returns VBox status code.
7925 * @param pVCpu The cross context virtual CPU structure.
7926 *
7927 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7928 * do not log!
7929 */
7930static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7931{
7932 uint32_t u32Sel, u32Limit, u32Attr;
7933 uint64_t u64Base;
7934 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7935 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7936 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7937 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7938 AssertRCReturn(rc, rc);
7939
7940 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7941 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7942 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7943 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7944 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7945 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7946 /* TR is the only selector that can never be unusable. */
7947 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7948 return VINF_SUCCESS;
7949}
7950
7951
7952/**
7953 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7954 *
7955 * @returns VBox status code.
7956 * @param pVCpu The cross context virtual CPU structure.
7957 *
7958 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7959 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7960 * instead!!!
7961 */
7962static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7963{
7964 uint64_t u64Val;
7965 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7966 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7967 {
7968 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7969 if (RT_SUCCESS(rc))
7970 {
7971 pCtx->rip = u64Val;
7972 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7973 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7974 }
7975 return rc;
7976 }
7977 return VINF_SUCCESS;
7978}
7979
7980
7981/**
7982 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7983 *
7984 * @returns VBox status code.
7985 * @param pVCpu The cross context virtual CPU structure.
7986 * @param pVmcsInfo The VMCS info. object.
7987 *
7988 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7989 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7990 * instead!!!
7991 */
7992static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7993{
7994 uint32_t u32Val;
7995 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7996 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7997 {
7998 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7999 if (RT_SUCCESS(rc))
8000 {
8001 pCtx->eflags.u32 = u32Val;
8002
8003 /* Restore eflags for real-on-v86-mode hack. */
8004 if (pVmcsInfo->RealMode.fRealOnV86Active)
8005 {
8006 pCtx->eflags.Bits.u1VM = 0;
8007 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
8008 }
8009 }
8010 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
8011 return rc;
8012 }
8013 return VINF_SUCCESS;
8014}
8015
8016
8017/**
8018 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
8019 * context.
8020 *
8021 * @returns VBox status code.
8022 * @param pVCpu The cross context virtual CPU structure.
8023 * @param pVmcsInfo The VMCS info. object.
8024 *
8025 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
8026 * do not log!
8027 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
8028 * instead!!!
8029 */
8030static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
8031{
8032 uint32_t u32Val;
8033 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
8034 if (RT_SUCCESS(rc))
8035 {
8036 if (!u32Val)
8037 {
8038 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8039 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
8040
8041 CPUMSetGuestNmiBlocking(pVCpu, false);
8042 }
8043 else
8044 {
8045 /*
8046 * We must import RIP here to set our EM interrupt-inhibited state.
8047 * We also import RFLAGS as our code that evaluates pending interrupts
8048 * before VM-entry requires it.
8049 */
8050 rc = hmR0VmxImportGuestRip(pVCpu);
8051 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8052 if (RT_SUCCESS(rc))
8053 {
8054 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
8055 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
8056 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
8057 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
8058
8059 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8060 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
8061 }
8062 }
8063 }
8064 return rc;
8065}
8066
8067
8068/**
8069 * Worker for VMXR0ImportStateOnDemand.
8070 *
8071 * @returns VBox status code.
8072 * @param pVCpu The cross context virtual CPU structure.
8073 * @param pVmcsInfo The VMCS info. object.
8074 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8075 */
8076static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
8077{
8078#define VMXLOCAL_BREAK_RC(a_rc) \
8079 if (RT_SUCCESS(a_rc)) \
8080 { } \
8081 else \
8082 break
8083
8084 int rc = VINF_SUCCESS;
8085 PVM pVM = pVCpu->CTX_SUFF(pVM);
8086 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8087 uint64_t u64Val;
8088 uint32_t u32Val;
8089
8090 /*
8091 * Note! This is hack to workaround a mysterious BSOD observed with release builds
8092 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
8093 * neither are other host platforms.
8094 *
8095 * Committing this temporarily as it prevents BSOD.
8096 *
8097 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
8098 */
8099#ifdef RT_OS_WINDOWS
8100 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
8101 return VERR_HM_IPE_1;
8102#endif
8103
8104 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
8105
8106 /*
8107 * We disable interrupts to make the updating of the state and in particular
8108 * the fExtrn modification atomic wrt to preemption hooks.
8109 */
8110 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
8111
8112 fWhat &= pCtx->fExtrn;
8113 if (fWhat)
8114 {
8115 do
8116 {
8117 if (fWhat & CPUMCTX_EXTRN_RIP)
8118 {
8119 rc = hmR0VmxImportGuestRip(pVCpu);
8120 VMXLOCAL_BREAK_RC(rc);
8121 }
8122
8123 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
8124 {
8125 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8126 VMXLOCAL_BREAK_RC(rc);
8127 }
8128
8129 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
8130 {
8131 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
8132 VMXLOCAL_BREAK_RC(rc);
8133 }
8134
8135 if (fWhat & CPUMCTX_EXTRN_RSP)
8136 {
8137 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
8138 VMXLOCAL_BREAK_RC(rc);
8139 pCtx->rsp = u64Val;
8140 }
8141
8142 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
8143 {
8144 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
8145 if (fWhat & CPUMCTX_EXTRN_CS)
8146 {
8147 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
8148 rc |= hmR0VmxImportGuestRip(pVCpu);
8149 if (fRealOnV86Active)
8150 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
8151 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
8152 }
8153 if (fWhat & CPUMCTX_EXTRN_SS)
8154 {
8155 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
8156 if (fRealOnV86Active)
8157 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
8158 }
8159 if (fWhat & CPUMCTX_EXTRN_DS)
8160 {
8161 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
8162 if (fRealOnV86Active)
8163 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
8164 }
8165 if (fWhat & CPUMCTX_EXTRN_ES)
8166 {
8167 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
8168 if (fRealOnV86Active)
8169 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
8170 }
8171 if (fWhat & CPUMCTX_EXTRN_FS)
8172 {
8173 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
8174 if (fRealOnV86Active)
8175 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
8176 }
8177 if (fWhat & CPUMCTX_EXTRN_GS)
8178 {
8179 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
8180 if (fRealOnV86Active)
8181 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
8182 }
8183 VMXLOCAL_BREAK_RC(rc);
8184 }
8185
8186 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
8187 {
8188 if (fWhat & CPUMCTX_EXTRN_LDTR)
8189 rc |= hmR0VmxImportGuestLdtr(pVCpu);
8190
8191 if (fWhat & CPUMCTX_EXTRN_GDTR)
8192 {
8193 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
8194 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
8195 pCtx->gdtr.pGdt = u64Val;
8196 pCtx->gdtr.cbGdt = u32Val;
8197 }
8198
8199 /* Guest IDTR. */
8200 if (fWhat & CPUMCTX_EXTRN_IDTR)
8201 {
8202 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
8203 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
8204 pCtx->idtr.pIdt = u64Val;
8205 pCtx->idtr.cbIdt = u32Val;
8206 }
8207
8208 /* Guest TR. */
8209 if (fWhat & CPUMCTX_EXTRN_TR)
8210 {
8211 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
8212 don't need to import that one. */
8213 if (!pVmcsInfo->RealMode.fRealOnV86Active)
8214 rc |= hmR0VmxImportGuestTr(pVCpu);
8215 }
8216 VMXLOCAL_BREAK_RC(rc);
8217 }
8218
8219 if (fWhat & CPUMCTX_EXTRN_DR7)
8220 {
8221 if (!pVCpu->hm.s.fUsingHyperDR7)
8222 {
8223 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
8224 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
8225 VMXLOCAL_BREAK_RC(rc);
8226 pCtx->dr[7] = u32Val;
8227 }
8228 }
8229
8230 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
8231 {
8232 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
8233 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
8234 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
8235 pCtx->SysEnter.cs = u32Val;
8236 VMXLOCAL_BREAK_RC(rc);
8237 }
8238
8239#if HC_ARCH_BITS == 64
8240 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
8241 {
8242 if ( pVM->hm.s.fAllow64BitGuests
8243 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8244 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
8245 }
8246
8247 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
8248 {
8249 if ( pVM->hm.s.fAllow64BitGuests
8250 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8251 {
8252 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
8253 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
8254 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
8255 }
8256 }
8257#endif
8258
8259 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
8260#if HC_ARCH_BITS == 32
8261 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
8262#endif
8263 )
8264 {
8265 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
8266 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
8267 Assert(pMsrs);
8268 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
8269 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
8270 for (uint32_t i = 0; i < cMsrs; i++)
8271 {
8272 uint32_t const idMsr = pMsrs[i].u32Msr;
8273 switch (idMsr)
8274 {
8275 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
8276 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
8277 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
8278#if HC_ARCH_BITS == 32
8279 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
8280 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
8281 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
8282 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
8283#endif
8284 default:
8285 {
8286 pCtx->fExtrn = 0;
8287 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
8288 ASMSetFlags(fEFlags);
8289 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
8290 return VERR_HM_UNEXPECTED_LD_ST_MSR;
8291 }
8292 }
8293 }
8294 }
8295
8296 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
8297 {
8298 uint64_t u64Shadow;
8299 if (fWhat & CPUMCTX_EXTRN_CR0)
8300 {
8301 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8302 * remove when we drop 32-bit host w/ 64-bit host support, see
8303 * @bugref{9180#c39}. */
8304 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
8305#if HC_ARCH_BITS == 32
8306 uint32_t u32Shadow;
8307 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
8308 u64Shadow = u32Shadow;
8309#else
8310 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
8311#endif
8312 VMXLOCAL_BREAK_RC(rc);
8313 u64Val = u32Val;
8314 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
8315 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
8316#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8317 /*
8318 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
8319 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
8320 */
8321 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8322 {
8323 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
8324 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
8325 }
8326#endif
8327 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
8328 CPUMSetGuestCR0(pVCpu, u64Val);
8329 VMMRZCallRing3Enable(pVCpu);
8330 }
8331
8332 if (fWhat & CPUMCTX_EXTRN_CR4)
8333 {
8334 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8335 * remove when we drop 32-bit host w/ 64-bit host support, see
8336 * @bugref{9180#c39}. */
8337 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
8338#if HC_ARCH_BITS == 32
8339 uint32_t u32Shadow;
8340 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
8341 u64Shadow = u32Shadow;
8342#else
8343 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
8344#endif
8345 VMXLOCAL_BREAK_RC(rc);
8346 u64Val = u32Val;
8347 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
8348 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
8349#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8350 /*
8351 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
8352 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
8353 */
8354 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8355 {
8356 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
8357 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
8358 }
8359#endif
8360 pCtx->cr4 = u64Val;
8361 }
8362
8363 if (fWhat & CPUMCTX_EXTRN_CR3)
8364 {
8365 /* CR0.PG bit changes are always intercepted, so it's up to date. */
8366 if ( pVM->hm.s.vmx.fUnrestrictedGuest
8367 || ( pVM->hm.s.fNestedPaging
8368 && CPUMIsGuestPagingEnabledEx(pCtx)))
8369 {
8370 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
8371 VMXLOCAL_BREAK_RC(rc);
8372 if (pCtx->cr3 != u64Val)
8373 {
8374 pCtx->cr3 = u64Val;
8375 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
8376 }
8377
8378 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
8379 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
8380 if (CPUMIsGuestInPAEModeEx(pCtx))
8381 {
8382 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
8383 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
8384 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
8385 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
8386 VMXLOCAL_BREAK_RC(rc);
8387 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
8388 }
8389 }
8390 }
8391 }
8392
8393#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8394 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
8395 {
8396 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
8397 && !CPUMIsGuestInVmxNonRootMode(pCtx))
8398 {
8399 Assert(CPUMIsGuestInVmxRootMode(pCtx));
8400 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
8401 VMXLOCAL_BREAK_RC(rc);
8402 }
8403 }
8404#endif
8405 } while (0);
8406
8407 if (RT_SUCCESS(rc))
8408 {
8409 /* Update fExtrn. */
8410 pCtx->fExtrn &= ~fWhat;
8411
8412 /* If everything has been imported, clear the HM keeper bit. */
8413 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8414 {
8415 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8416 Assert(!pCtx->fExtrn);
8417 }
8418 }
8419 }
8420 else
8421 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8422
8423 ASMSetFlags(fEFlags);
8424
8425 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8426
8427 if (RT_SUCCESS(rc))
8428 { /* likely */ }
8429 else
8430 return rc;
8431
8432 /*
8433 * Honor any pending CR3 updates.
8434 *
8435 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
8436 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8437 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8438 *
8439 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8440 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8441 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8442 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8443 *
8444 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8445 */
8446 if (VMMRZCallRing3IsEnabled(pVCpu))
8447 {
8448 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8449 {
8450 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8451 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8452 }
8453
8454 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8455 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8456
8457 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8458 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8459 }
8460
8461 return VINF_SUCCESS;
8462#undef VMXLOCAL_BREAK_RC
8463}
8464
8465
8466/**
8467 * Saves the guest state from the VMCS into the guest-CPU context.
8468 *
8469 * @returns VBox status code.
8470 * @param pVCpu The cross context virtual CPU structure.
8471 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8472 */
8473VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
8474{
8475 AssertPtr(pVCpu);
8476 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8477 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8478}
8479
8480
8481/**
8482 * Check per-VM and per-VCPU force flag actions that require us to go back to
8483 * ring-3 for one reason or another.
8484 *
8485 * @returns Strict VBox status code (i.e. informational status codes too)
8486 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8487 * ring-3.
8488 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8489 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8490 * interrupts)
8491 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8492 * all EMTs to be in ring-3.
8493 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8494 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8495 * to the EM loop.
8496 *
8497 * @param pVCpu The cross context virtual CPU structure.
8498 * @param fStepping Whether we are single-stepping the guest using the
8499 * hypervisor debugger.
8500 */
8501static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
8502{
8503 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8504
8505 /*
8506 * Update pending interrupts into the APIC's IRR.
8507 */
8508 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8509 APICUpdatePendingInterrupts(pVCpu);
8510
8511 /*
8512 * Anything pending? Should be more likely than not if we're doing a good job.
8513 */
8514 PVM pVM = pVCpu->CTX_SUFF(pVM);
8515 if ( !fStepping
8516 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8517 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8518 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8519 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8520 return VINF_SUCCESS;
8521
8522 /* Pending PGM C3 sync. */
8523 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8524 {
8525 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8526 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8527 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8528 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8529 if (rcStrict2 != VINF_SUCCESS)
8530 {
8531 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
8532 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
8533 return rcStrict2;
8534 }
8535 }
8536
8537 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8538 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8539 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8540 {
8541 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8542 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8543 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
8544 return rc2;
8545 }
8546
8547 /* Pending VM request packets, such as hardware interrupts. */
8548 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8549 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8550 {
8551 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8552 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8553 return VINF_EM_PENDING_REQUEST;
8554 }
8555
8556 /* Pending PGM pool flushes. */
8557 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8558 {
8559 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8560 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8561 return VINF_PGM_POOL_FLUSH_PENDING;
8562 }
8563
8564 /* Pending DMA requests. */
8565 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8566 {
8567 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8568 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8569 return VINF_EM_RAW_TO_R3;
8570 }
8571
8572 return VINF_SUCCESS;
8573}
8574
8575
8576/**
8577 * Converts any TRPM trap into a pending HM event. This is typically used when
8578 * entering from ring-3 (not longjmp returns).
8579 *
8580 * @param pVCpu The cross context virtual CPU structure.
8581 */
8582static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
8583{
8584 Assert(TRPMHasTrap(pVCpu));
8585 Assert(!pVCpu->hm.s.Event.fPending);
8586
8587 uint8_t uVector;
8588 TRPMEVENT enmTrpmEvent;
8589 RTGCUINT uErrCode;
8590 RTGCUINTPTR GCPtrFaultAddress;
8591 uint8_t cbInstr;
8592
8593 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
8594 AssertRC(rc);
8595
8596 uint32_t u32IntInfo;
8597 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8598 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
8599
8600 rc = TRPMResetTrap(pVCpu);
8601 AssertRC(rc);
8602 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8603 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8604
8605 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8606}
8607
8608
8609/**
8610 * Converts the pending HM event into a TRPM trap.
8611 *
8612 * @param pVCpu The cross context virtual CPU structure.
8613 */
8614static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
8615{
8616 Assert(pVCpu->hm.s.Event.fPending);
8617
8618 /* If a trap was already pending, we did something wrong! */
8619 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8620
8621 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8622 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8623 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8624
8625 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8626
8627 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8628 AssertRC(rc);
8629
8630 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8631 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8632
8633 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8634 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8635 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
8636 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8637
8638 /* We're now done converting the pending event. */
8639 pVCpu->hm.s.Event.fPending = false;
8640}
8641
8642
8643/**
8644 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8645 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8646 *
8647 * @param pVCpu The cross context virtual CPU structure.
8648 * @param pVmcsInfo The VMCS info. object.
8649 */
8650static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8651{
8652 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8653 {
8654 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8655 {
8656 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8657 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8658 AssertRC(rc);
8659 }
8660 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8661}
8662
8663
8664/**
8665 * Clears the interrupt-window exiting control in the VMCS.
8666 *
8667 * @param pVmcsInfo The VMCS info. object.
8668 */
8669DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8670{
8671 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8672 {
8673 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8674 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8675 }
8676 return VINF_SUCCESS;
8677}
8678
8679
8680/**
8681 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8682 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8683 *
8684 * @param pVCpu The cross context virtual CPU structure.
8685 * @param pVmcsInfo The VMCS info. object.
8686 */
8687static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8688{
8689 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8690 {
8691 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8692 {
8693 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8694 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8695 AssertRC(rc);
8696 Log4Func(("Setup NMI-window exiting\n"));
8697 }
8698 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8699}
8700
8701
8702/**
8703 * Clears the NMI-window exiting control in the VMCS.
8704 *
8705 * @param pVmcsInfo The VMCS info. object.
8706 */
8707DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8708{
8709 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8710 {
8711 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8712 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8713 }
8714 return VINF_SUCCESS;
8715}
8716
8717
8718/**
8719 * Does the necessary state syncing before returning to ring-3 for any reason
8720 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8721 *
8722 * @returns VBox status code.
8723 * @param pVCpu The cross context virtual CPU structure.
8724 * @param fImportState Whether to import the guest state from the VMCS back
8725 * to the guest-CPU context.
8726 *
8727 * @remarks No-long-jmp zone!!!
8728 */
8729static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
8730{
8731 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8732 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8733
8734 RTCPUID const idCpu = RTMpCpuId();
8735 Log4Func(("HostCpuId=%u\n", idCpu));
8736
8737 /*
8738 * !!! IMPORTANT !!!
8739 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8740 */
8741
8742 /* Save the guest state if necessary. */
8743 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8744 if (fImportState)
8745 {
8746 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8747 AssertRCReturn(rc, rc);
8748 }
8749
8750 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8751 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8752 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8753
8754 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8755#ifdef VBOX_STRICT
8756 if (CPUMIsHyperDebugStateActive(pVCpu))
8757 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8758#endif
8759 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8760 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8761 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8762
8763#if HC_ARCH_BITS == 64
8764 /* Restore host-state bits that VT-x only restores partially. */
8765 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8766 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8767 {
8768 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8769 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8770 }
8771 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8772#endif
8773
8774 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8775 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8776 {
8777 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8778 if (!fImportState)
8779 {
8780 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8781 AssertRCReturn(rc, rc);
8782 }
8783 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8784 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8785 }
8786 else
8787 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8788
8789 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8790 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8791
8792 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8793 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8794 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8795 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8796 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8797 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8798 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8799 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8800 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8801 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8802
8803 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8804
8805 /** @todo This partially defeats the purpose of having preemption hooks.
8806 * The problem is, deregistering the hooks should be moved to a place that
8807 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8808 * context.
8809 */
8810 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8811 AssertRCReturn(rc, rc);
8812
8813#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8814 /*
8815 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8816 * clear a shadow VMCS before allowing that VMCS to become active on another
8817 * logical processor. We may or may not be importing guest state which clears
8818 * it, so cover for it here.
8819 *
8820 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8821 */
8822 if ( pVmcsInfo->pvShadowVmcs
8823 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8824 {
8825 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8826 AssertRCReturn(rc, rc);
8827 }
8828
8829 /*
8830 * Flag that we need to re-import the host state if we switch to this VMCS before
8831 * executing guest or nested-guest code.
8832 */
8833 pVmcsInfo->idHostCpu = NIL_RTCPUID;
8834#endif
8835
8836 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8837 NOREF(idCpu);
8838 return VINF_SUCCESS;
8839}
8840
8841
8842/**
8843 * Leaves the VT-x session.
8844 *
8845 * @returns VBox status code.
8846 * @param pVCpu The cross context virtual CPU structure.
8847 *
8848 * @remarks No-long-jmp zone!!!
8849 */
8850static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8851{
8852 HM_DISABLE_PREEMPT(pVCpu);
8853 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8854 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8855 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8856
8857 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8858 and done this from the VMXR0ThreadCtxCallback(). */
8859 if (!pVCpu->hm.s.fLeaveDone)
8860 {
8861 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8862 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8863 pVCpu->hm.s.fLeaveDone = true;
8864 }
8865 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8866
8867 /*
8868 * !!! IMPORTANT !!!
8869 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8870 */
8871
8872 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8873 /** @todo Deregistering here means we need to VMCLEAR always
8874 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8875 * for calling VMMR0ThreadCtxHookDisable here! */
8876 VMMR0ThreadCtxHookDisable(pVCpu);
8877
8878 /* Leave HM context. This takes care of local init (term). */
8879 int rc = HMR0LeaveCpu(pVCpu);
8880
8881 HM_RESTORE_PREEMPT();
8882 return rc;
8883}
8884
8885
8886/**
8887 * Does the necessary state syncing before doing a longjmp to ring-3.
8888 *
8889 * @returns VBox status code.
8890 * @param pVCpu The cross context virtual CPU structure.
8891 *
8892 * @remarks No-long-jmp zone!!!
8893 */
8894DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8895{
8896 return hmR0VmxLeaveSession(pVCpu);
8897}
8898
8899
8900/**
8901 * Take necessary actions before going back to ring-3.
8902 *
8903 * An action requires us to go back to ring-3. This function does the necessary
8904 * steps before we can safely return to ring-3. This is not the same as longjmps
8905 * to ring-3, this is voluntary and prepares the guest so it may continue
8906 * executing outside HM (recompiler/IEM).
8907 *
8908 * @returns VBox status code.
8909 * @param pVCpu The cross context virtual CPU structure.
8910 * @param rcExit The reason for exiting to ring-3. Can be
8911 * VINF_VMM_UNKNOWN_RING3_CALL.
8912 */
8913static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8914{
8915 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8916
8917 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8918 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8919 {
8920 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8921 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8922 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8923 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8924 }
8925
8926 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8927 VMMRZCallRing3Disable(pVCpu);
8928 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8929
8930 /*
8931 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8932 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8933 *
8934 * This is because execution may continue from ring-3 and we would need to inject
8935 * the event from there (hence place it back in TRPM).
8936 */
8937 if (pVCpu->hm.s.Event.fPending)
8938 {
8939 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8940 Assert(!pVCpu->hm.s.Event.fPending);
8941
8942 /* Clear the events from the VMCS. */
8943 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8944 AssertRCReturn(rc, rc);
8945 }
8946#ifdef VBOX_STRICT
8947 else
8948 {
8949 /*
8950 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8951 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8952 * occasionally, see @bugref{9180#c42}.
8953 *
8954 * However, if the VM-entry failed, any VM entry-interruption info. field would
8955 * be left unmodified as the event would not have been injected to the guest. In
8956 * such cases, don't assert, we're not going to continue guest execution anyway.
8957 */
8958 uint32_t uExitReason;
8959 uint32_t uEntryIntInfo;
8960 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8961 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8962 AssertRC(rc);
8963 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8964 }
8965#endif
8966
8967 /*
8968 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8969 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8970 * (e.g. TPR below threshold).
8971 */
8972 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8973 {
8974 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8975 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8976 AssertRCReturn(rc, rc);
8977 }
8978
8979 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8980 and if we're injecting an event we should have a TRPM trap pending. */
8981 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8982#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8983 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8984#endif
8985
8986 /* Save guest state and restore host state bits. */
8987 int rc = hmR0VmxLeaveSession(pVCpu);
8988 AssertRCReturn(rc, rc);
8989 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8990
8991 /* Thread-context hooks are unregistered at this point!!! */
8992
8993 /* Sync recompiler state. */
8994 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8995 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8996 | CPUM_CHANGED_LDTR
8997 | CPUM_CHANGED_GDTR
8998 | CPUM_CHANGED_IDTR
8999 | CPUM_CHANGED_TR
9000 | CPUM_CHANGED_HIDDEN_SEL_REGS);
9001 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
9002 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
9003 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
9004
9005 Assert(!pVCpu->hm.s.fClearTrapFlag);
9006
9007 /* Update the exit-to-ring 3 reason. */
9008 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
9009
9010 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
9011 if ( rcExit != VINF_EM_RAW_INTERRUPT
9012 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
9013 {
9014 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
9015 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9016 }
9017
9018 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
9019
9020 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
9021 VMMRZCallRing3RemoveNotification(pVCpu);
9022 VMMRZCallRing3Enable(pVCpu);
9023
9024 return rc;
9025}
9026
9027
9028/**
9029 * VMMRZCallRing3() callback wrapper which saves the guest state before we
9030 * longjump to ring-3 and possibly get preempted.
9031 *
9032 * @returns VBox status code.
9033 * @param pVCpu The cross context virtual CPU structure.
9034 * @param enmOperation The operation causing the ring-3 longjump.
9035 * @param pvUser User argument, currently unused, NULL.
9036 */
9037static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
9038{
9039 RT_NOREF(pvUser);
9040 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
9041 {
9042 /*
9043 * !!! IMPORTANT !!!
9044 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
9045 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
9046 */
9047 VMMRZCallRing3RemoveNotification(pVCpu);
9048 VMMRZCallRing3Disable(pVCpu);
9049 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
9050 RTThreadPreemptDisable(&PreemptState);
9051
9052 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9053 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
9054 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
9055 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
9056
9057#if HC_ARCH_BITS == 64
9058 /* Restore host-state bits that VT-x only restores partially. */
9059 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
9060 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
9061 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
9062 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
9063#endif
9064
9065 /* Restore the lazy host MSRs as we're leaving VT-x context. */
9066 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
9067 hmR0VmxLazyRestoreHostMsrs(pVCpu);
9068
9069 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
9070 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
9071 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
9072
9073 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
9074 cleared as part of importing the guest state above. */
9075 hmR0VmxClearVmcs(pVmcsInfo);
9076
9077 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
9078 VMMR0ThreadCtxHookDisable(pVCpu);
9079 HMR0LeaveCpu(pVCpu);
9080 RTThreadPreemptRestore(&PreemptState);
9081 return VINF_SUCCESS;
9082 }
9083
9084 Assert(pVCpu);
9085 Assert(pvUser);
9086 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9087 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9088
9089 VMMRZCallRing3Disable(pVCpu);
9090 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9091
9092 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
9093
9094 int rc = hmR0VmxLongJmpToRing3(pVCpu);
9095 AssertRCReturn(rc, rc);
9096
9097 VMMRZCallRing3Enable(pVCpu);
9098 return VINF_SUCCESS;
9099}
9100
9101
9102/**
9103 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
9104 * stack.
9105 *
9106 * @returns Strict VBox status code (i.e. informational status codes too).
9107 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
9108 * @param pVCpu The cross context virtual CPU structure.
9109 * @param uValue The value to push to the guest stack.
9110 */
9111static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
9112{
9113 /*
9114 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
9115 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
9116 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
9117 */
9118 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9119 if (pCtx->sp == 1)
9120 return VINF_EM_RESET;
9121 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
9122 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
9123 AssertRC(rc);
9124 return rc;
9125}
9126
9127
9128/**
9129 * Injects an event into the guest upon VM-entry by updating the relevant fields
9130 * in the VM-entry area in the VMCS.
9131 *
9132 * @returns Strict VBox status code (i.e. informational status codes too).
9133 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
9134 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
9135 *
9136 * @param pVCpu The cross context virtual CPU structure.
9137 * @param pVmxTransient The VMX-transient structure.
9138 * @param pEvent The event being injected.
9139 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
9140 * will be updated if necessary. This cannot not be NULL.
9141 * @param fStepping Whether we're single-stepping guest execution and should
9142 * return VINF_EM_DBG_STEPPED if the event is injected
9143 * directly (registers modified by us, not by hardware on
9144 * VM-entry).
9145 */
9146static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
9147 uint32_t *pfIntrState)
9148{
9149 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
9150 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
9151 Assert(pfIntrState);
9152
9153 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9154 uint32_t u32IntInfo = pEvent->u64IntInfo;
9155 uint32_t const u32ErrCode = pEvent->u32ErrCode;
9156 uint32_t const cbInstr = pEvent->cbInstr;
9157 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
9158 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
9159 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
9160
9161#ifdef VBOX_STRICT
9162 /*
9163 * Validate the error-code-valid bit for hardware exceptions.
9164 * No error codes for exceptions in real-mode.
9165 *
9166 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9167 */
9168 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
9169 && !CPUMIsGuestInRealModeEx(pCtx))
9170 {
9171 switch (uVector)
9172 {
9173 case X86_XCPT_PF:
9174 case X86_XCPT_DF:
9175 case X86_XCPT_TS:
9176 case X86_XCPT_NP:
9177 case X86_XCPT_SS:
9178 case X86_XCPT_GP:
9179 case X86_XCPT_AC:
9180 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
9181 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
9182 RT_FALL_THRU();
9183 default:
9184 break;
9185 }
9186 }
9187
9188 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
9189 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
9190 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9191#endif
9192
9193 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
9194
9195 /*
9196 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
9197 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
9198 * interrupt handler in the (real-mode) guest.
9199 *
9200 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
9201 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
9202 */
9203 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
9204 {
9205 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
9206 {
9207 /*
9208 * For CPUs with unrestricted guest execution enabled and with the guest
9209 * in real-mode, we must not set the deliver-error-code bit.
9210 *
9211 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
9212 */
9213 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
9214 }
9215 else
9216 {
9217 PVM pVM = pVCpu->CTX_SUFF(pVM);
9218 Assert(PDMVmmDevHeapIsEnabled(pVM));
9219 Assert(pVM->hm.s.vmx.pRealModeTSS);
9220 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
9221
9222 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
9223 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9224 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
9225 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
9226 AssertRCReturn(rc2, rc2);
9227
9228 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
9229 size_t const cbIdtEntry = sizeof(X86IDTR16);
9230 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
9231 {
9232 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
9233 if (uVector == X86_XCPT_DF)
9234 return VINF_EM_RESET;
9235
9236 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
9237 No error codes for exceptions in real-mode. */
9238 if (uVector == X86_XCPT_GP)
9239 {
9240 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
9241 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9242 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9243 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9244 HMEVENT EventXcptDf;
9245 RT_ZERO(EventXcptDf);
9246 EventXcptDf.u64IntInfo = uXcptDfInfo;
9247 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
9248 }
9249
9250 /*
9251 * If we're injecting an event with no valid IDT entry, inject a #GP.
9252 * No error codes for exceptions in real-mode.
9253 *
9254 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9255 */
9256 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
9257 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9258 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9259 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9260 HMEVENT EventXcptGp;
9261 RT_ZERO(EventXcptGp);
9262 EventXcptGp.u64IntInfo = uXcptGpInfo;
9263 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
9264 }
9265
9266 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
9267 uint16_t uGuestIp = pCtx->ip;
9268 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
9269 {
9270 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
9271 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
9272 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9273 }
9274 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
9275 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9276
9277 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
9278 X86IDTR16 IdtEntry;
9279 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
9280 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
9281 AssertRCReturn(rc2, rc2);
9282
9283 /* Construct the stack frame for the interrupt/exception handler. */
9284 VBOXSTRICTRC rcStrict;
9285 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
9286 if (rcStrict == VINF_SUCCESS)
9287 {
9288 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
9289 if (rcStrict == VINF_SUCCESS)
9290 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
9291 }
9292
9293 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
9294 if (rcStrict == VINF_SUCCESS)
9295 {
9296 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
9297 pCtx->rip = IdtEntry.offSel;
9298 pCtx->cs.Sel = IdtEntry.uSel;
9299 pCtx->cs.ValidSel = IdtEntry.uSel;
9300 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
9301 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
9302 && uVector == X86_XCPT_PF)
9303 pCtx->cr2 = GCPtrFault;
9304
9305 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
9306 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
9307 | HM_CHANGED_GUEST_RSP);
9308
9309 /*
9310 * If we delivered a hardware exception (other than an NMI) and if there was
9311 * block-by-STI in effect, we should clear it.
9312 */
9313 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9314 {
9315 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
9316 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
9317 Log4Func(("Clearing inhibition due to STI\n"));
9318 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
9319 }
9320
9321 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
9322 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
9323
9324 /*
9325 * The event has been truly dispatched to the guest. Mark it as no longer pending so
9326 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
9327 */
9328 pVCpu->hm.s.Event.fPending = false;
9329
9330 /*
9331 * If we eventually support nested-guest execution without unrestricted guest execution,
9332 * we should set fInterceptEvents here.
9333 */
9334 Assert(!pVmxTransient->fIsNestedGuest);
9335
9336 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
9337 if (fStepping)
9338 rcStrict = VINF_EM_DBG_STEPPED;
9339 }
9340 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9341 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9342 return rcStrict;
9343 }
9344 }
9345
9346 /*
9347 * Validate.
9348 */
9349 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9350 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9351
9352 /*
9353 * Inject the event into the VMCS.
9354 */
9355 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9356 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9357 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9358 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9359 AssertRCReturn(rc, rc);
9360
9361 /*
9362 * Update guest CR2 if this is a page-fault.
9363 */
9364 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9365 pCtx->cr2 = GCPtrFault;
9366
9367 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9368 return VINF_SUCCESS;
9369}
9370
9371
9372/**
9373 * Evaluates the event to be delivered to the guest and sets it as the pending
9374 * event.
9375 *
9376 * @returns Strict VBox status code (i.e. informational status codes too).
9377 * @param pVCpu The cross context virtual CPU structure.
9378 * @param pVmxTransient The VMX-transient structure.
9379 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9380 */
9381static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9382{
9383 Assert(pfIntrState);
9384 Assert(!TRPMHasTrap(pVCpu));
9385
9386 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9387 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9388 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9389
9390 /*
9391 * Get the current interruptibility-state of the guest or nested-guest and
9392 * then figure out what needs to be injected.
9393 */
9394 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
9395 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9396 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9397 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9398
9399 /* We don't support block-by-SMI yet.*/
9400 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
9401
9402 /* Block-by-STI must not be set when interrupts are disabled. */
9403 if (fBlockSti)
9404 {
9405 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
9406 Assert(pCtx->eflags.Bits.u1IF);
9407 }
9408
9409 /* Update interruptibility state to the caller. */
9410 *pfIntrState = fIntrState;
9411
9412 /*
9413 * Toggling of interrupt force-flags here is safe since we update TRPM on
9414 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
9415 * We must NOT restore these force-flags.
9416 */
9417
9418 /** @todo SMI. SMIs take priority over NMIs. */
9419
9420 /*
9421 * Check if an NMI is pending and if the guest or nested-guest can receive them.
9422 * NMIs take priority over external interrupts.
9423 */
9424 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
9425 {
9426 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
9427 if ( !pVCpu->hm.s.Event.fPending
9428 && !fBlockNmi
9429 && !fBlockSti
9430 && !fBlockMovSS)
9431 {
9432#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9433 if ( fIsNestedGuest
9434 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
9435 return IEMExecVmxVmexitXcptNmi(pVCpu);
9436#endif
9437 hmR0VmxSetPendingXcptNmi(pVCpu);
9438 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9439 Log4Func(("Pending NMI\n"));
9440 }
9441 else if (!fIsNestedGuest)
9442 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9443 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
9444 }
9445 /*
9446 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
9447 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
9448 * the interrupt. We can no longer re-request it from the APIC.
9449 */
9450 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9451 && !pVCpu->hm.s.fSingleInstruction)
9452 {
9453 Assert(!DBGFIsStepping(pVCpu));
9454 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9455 AssertRCReturn(rc, rc);
9456
9457 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
9458 if ( !pVCpu->hm.s.Event.fPending
9459 && !fBlockInt
9460 && !fBlockSti
9461 && !fBlockMovSS)
9462 {
9463#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9464 if ( fIsNestedGuest
9465 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9466 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9467 {
9468 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9469 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9470 return rcStrict;
9471 }
9472#endif
9473 uint8_t u8Interrupt;
9474 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9475 if (RT_SUCCESS(rc))
9476 {
9477#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9478 if ( fIsNestedGuest
9479 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9480 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9481 {
9482 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9483 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
9484 return rcStrict;
9485 }
9486#endif
9487 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9488 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9489 }
9490 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9491 {
9492 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9493
9494 if ( !fIsNestedGuest
9495 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9496 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9497 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
9498
9499 /*
9500 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9501 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9502 * need to re-set this force-flag here.
9503 */
9504 }
9505 else
9506 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9507 }
9508 else if (!fIsNestedGuest)
9509 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9510 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
9511 }
9512
9513 return VINF_SUCCESS;
9514}
9515
9516
9517/**
9518 * Injects any pending events into the guest if the guest is in a state to
9519 * receive them.
9520 *
9521 * @returns Strict VBox status code (i.e. informational status codes too).
9522 * @param pVCpu The cross context virtual CPU structure.
9523 * @param pVmxTransient The VMX-transient structure.
9524 * @param fIntrState The VT-x guest-interruptibility state.
9525 * @param fStepping Whether we are single-stepping the guest using the
9526 * hypervisor debugger and should return
9527 * VINF_EM_DBG_STEPPED if the event was dispatched
9528 * directly.
9529 */
9530static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9531{
9532 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9533 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9534
9535 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9536 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9537
9538 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9539 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9540 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9541 Assert(!TRPMHasTrap(pVCpu));
9542
9543 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9544 if (pVCpu->hm.s.Event.fPending)
9545 {
9546 /*
9547 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9548 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9549 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9550 *
9551 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9552 */
9553 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9554#ifdef VBOX_STRICT
9555 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9556 {
9557 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9558 Assert(!fBlockInt);
9559 Assert(!fBlockSti);
9560 Assert(!fBlockMovSS);
9561 }
9562 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9563 {
9564 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9565 Assert(!fBlockSti);
9566 Assert(!fBlockMovSS);
9567 Assert(!fBlockNmi);
9568 }
9569#endif
9570 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9571 uIntType));
9572
9573 /*
9574 * Inject the event and get any changes to the guest-interruptibility state.
9575 *
9576 * The guest-interruptibility state may need to be updated if we inject the event
9577 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9578 */
9579 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9580 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9581
9582 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9583 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9584 else
9585 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9586 }
9587
9588 /*
9589 * Update the guest-interruptibility state.
9590 *
9591 * This is required for the real-on-v86 software interrupt injection case above, as well as
9592 * updates to the guest state from ring-3 or IEM/REM.
9593 */
9594 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9595 AssertRCReturn(rc, rc);
9596
9597 /*
9598 * There's no need to clear the VM-entry interruption-information field here if we're not
9599 * injecting anything. VT-x clears the valid bit on every VM-exit.
9600 *
9601 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9602 */
9603
9604 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9605 NOREF(fBlockMovSS); NOREF(fBlockSti);
9606 return rcStrict;
9607}
9608
9609
9610/**
9611 * Enters the VT-x session.
9612 *
9613 * @returns VBox status code.
9614 * @param pVCpu The cross context virtual CPU structure.
9615 */
9616VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9617{
9618 AssertPtr(pVCpu);
9619 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9620 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9621
9622 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9623 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9624 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9625
9626#ifdef VBOX_STRICT
9627 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9628 RTCCUINTREG uHostCr4 = ASMGetCR4();
9629 if (!(uHostCr4 & X86_CR4_VMXE))
9630 {
9631 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9632 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9633 }
9634#endif
9635
9636 /*
9637 * Load the appropriate VMCS as the current and active one.
9638 */
9639 PVMXVMCSINFO pVmcsInfo;
9640 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9641 if (!fInNestedGuestMode)
9642 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9643 else
9644 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9645 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9646 if (RT_SUCCESS(rc))
9647 {
9648 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9649 pVCpu->hm.s.fLeaveDone = false;
9650 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9651
9652 /*
9653 * Do the EMT scheduled L1D flush here if needed.
9654 */
9655 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9656 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9657 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9658 hmR0MdsClear();
9659 }
9660 return rc;
9661}
9662
9663
9664/**
9665 * The thread-context callback (only on platforms which support it).
9666 *
9667 * @param enmEvent The thread-context event.
9668 * @param pVCpu The cross context virtual CPU structure.
9669 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9670 * @thread EMT(pVCpu)
9671 */
9672VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9673{
9674 AssertPtr(pVCpu);
9675 RT_NOREF1(fGlobalInit);
9676
9677 switch (enmEvent)
9678 {
9679 case RTTHREADCTXEVENT_OUT:
9680 {
9681 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9682 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9683 VMCPU_ASSERT_EMT(pVCpu);
9684
9685 /* No longjmps (logger flushes, locks) in this fragile context. */
9686 VMMRZCallRing3Disable(pVCpu);
9687 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9688
9689 /* Restore host-state (FPU, debug etc.) */
9690 if (!pVCpu->hm.s.fLeaveDone)
9691 {
9692 /*
9693 * Do -not- import the guest-state here as we might already be in the middle of importing
9694 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9695 */
9696 hmR0VmxLeave(pVCpu, false /* fImportState */);
9697 pVCpu->hm.s.fLeaveDone = true;
9698 }
9699
9700 /* Leave HM context, takes care of local init (term). */
9701 int rc = HMR0LeaveCpu(pVCpu);
9702 AssertRC(rc);
9703
9704 /* Restore longjmp state. */
9705 VMMRZCallRing3Enable(pVCpu);
9706 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9707 break;
9708 }
9709
9710 case RTTHREADCTXEVENT_IN:
9711 {
9712 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9713 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9714 VMCPU_ASSERT_EMT(pVCpu);
9715
9716 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9717 VMMRZCallRing3Disable(pVCpu);
9718 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9719
9720 /* Initialize the bare minimum state required for HM. This takes care of
9721 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9722 int rc = hmR0EnterCpu(pVCpu);
9723 AssertRC(rc);
9724 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9725 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9726
9727 /* Load the active VMCS as the current one. */
9728 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9729 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9730 AssertRC(rc);
9731 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9732 pVCpu->hm.s.fLeaveDone = false;
9733
9734 /* Do the EMT scheduled L1D flush if needed. */
9735 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9736 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9737
9738 /* Restore longjmp state. */
9739 VMMRZCallRing3Enable(pVCpu);
9740 break;
9741 }
9742
9743 default:
9744 break;
9745 }
9746}
9747
9748
9749/**
9750 * Exports the host state into the VMCS host-state area.
9751 * Sets up the VM-exit MSR-load area.
9752 *
9753 * The CPU state will be loaded from these fields on every successful VM-exit.
9754 *
9755 * @returns VBox status code.
9756 * @param pVCpu The cross context virtual CPU structure.
9757 *
9758 * @remarks No-long-jump zone!!!
9759 */
9760static int hmR0VmxExportHostState(PVMCPU pVCpu)
9761{
9762 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9763
9764 int rc = VINF_SUCCESS;
9765 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9766 {
9767 rc = hmR0VmxExportHostControlRegs();
9768 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9769
9770 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9771 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9772
9773 rc = hmR0VmxExportHostMsrs(pVCpu);
9774 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9775
9776 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9777 }
9778 return rc;
9779}
9780
9781
9782/**
9783 * Saves the host state in the VMCS host-state.
9784 *
9785 * @returns VBox status code.
9786 * @param pVCpu The cross context virtual CPU structure.
9787 *
9788 * @remarks No-long-jump zone!!!
9789 */
9790VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9791{
9792 AssertPtr(pVCpu);
9793 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9794
9795 /*
9796 * Export the host state here while entering HM context.
9797 * When thread-context hooks are used, we might get preempted and have to re-save the host
9798 * state but most of the time we won't be, so do it here before we disable interrupts.
9799 */
9800 return hmR0VmxExportHostState(pVCpu);
9801}
9802
9803
9804/**
9805 * Exports the guest state into the VMCS guest-state area.
9806 *
9807 * The will typically be done before VM-entry when the guest-CPU state and the
9808 * VMCS state may potentially be out of sync.
9809 *
9810 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9811 * VM-entry controls.
9812 * Sets up the appropriate VMX non-root function to execute guest code based on
9813 * the guest CPU mode.
9814 *
9815 * @returns VBox strict status code.
9816 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9817 * without unrestricted guest execution and the VMMDev is not presently
9818 * mapped (e.g. EFI32).
9819 *
9820 * @param pVCpu The cross context virtual CPU structure.
9821 * @param pVmxTransient The VMX-transient structure.
9822 *
9823 * @remarks No-long-jump zone!!!
9824 */
9825static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9826{
9827 AssertPtr(pVCpu);
9828 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9829 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9830
9831 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9832
9833 /*
9834 * Determine real-on-v86 mode.
9835 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9836 */
9837 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9838 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9839 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9840 pVmcsInfo->RealMode. fRealOnV86Active = false;
9841 else
9842 {
9843 Assert(!pVmxTransient->fIsNestedGuest);
9844 pVmcsInfo->RealMode.fRealOnV86Active = true;
9845 }
9846
9847 /*
9848 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9849 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9850 */
9851 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9852 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9853 * be a need to evaluate this everytime since I'm pretty sure we intercept
9854 * all guest paging mode changes. */
9855 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9856 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9857
9858 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9859 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9860
9861 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9862 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9863
9864 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9865 if (rcStrict == VINF_SUCCESS)
9866 { /* likely */ }
9867 else
9868 {
9869 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9870 return rcStrict;
9871 }
9872
9873 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9874 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9875
9876 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9877 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9878
9879 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9880 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9881
9882 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9883 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9884
9885 rc = hmR0VmxExportGuestRip(pVCpu);
9886 rc |= hmR0VmxExportGuestRsp(pVCpu);
9887 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9888 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9889
9890 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9891 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9892
9893 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9894 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9895 | HM_CHANGED_GUEST_CR2
9896 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9897 | HM_CHANGED_GUEST_X87
9898 | HM_CHANGED_GUEST_SSE_AVX
9899 | HM_CHANGED_GUEST_OTHER_XSAVE
9900 | HM_CHANGED_GUEST_XCRx
9901 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9902 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9903 | HM_CHANGED_GUEST_TSC_AUX
9904 | HM_CHANGED_GUEST_OTHER_MSRS
9905 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9906
9907 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9908 return rc;
9909}
9910
9911
9912/**
9913 * Exports the state shared between the host and guest into the VMCS.
9914 *
9915 * @param pVCpu The cross context virtual CPU structure.
9916 * @param pVmxTransient The VMX-transient structure.
9917 *
9918 * @remarks No-long-jump zone!!!
9919 */
9920static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9921{
9922 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9923 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9924
9925 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9926 {
9927 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9928 AssertRC(rc);
9929 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9930
9931 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9932 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9933 {
9934 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9935 AssertRC(rc);
9936 }
9937 }
9938
9939 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9940 {
9941 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9942 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9943 }
9944
9945 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9946 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9947}
9948
9949
9950/**
9951 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9952 *
9953 * @returns Strict VBox status code (i.e. informational status codes too).
9954 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9955 * without unrestricted guest execution and the VMMDev is not presently
9956 * mapped (e.g. EFI32).
9957 *
9958 * @param pVCpu The cross context virtual CPU structure.
9959 * @param pVmxTransient The VMX-transient structure.
9960 *
9961 * @remarks No-long-jump zone!!!
9962 */
9963static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9964{
9965 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9966 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9967 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9968
9969#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9970 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9971#endif
9972
9973 /*
9974 * For many exits it's only RIP that changes and hence try to export it first
9975 * without going through a lot of change flag checks.
9976 */
9977 VBOXSTRICTRC rcStrict;
9978 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9979 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9980 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9981 {
9982 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9983 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9984 { /* likely */}
9985 else
9986 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9987 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9988 }
9989 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9990 {
9991 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9992 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9993 { /* likely */}
9994 else
9995 {
9996 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9997 VBOXSTRICTRC_VAL(rcStrict)));
9998 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9999 return rcStrict;
10000 }
10001 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
10002 }
10003 else
10004 rcStrict = VINF_SUCCESS;
10005
10006#ifdef VBOX_STRICT
10007 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
10008 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
10009 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
10010 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
10011 ("fCtxChanged=%#RX64\n", fCtxChanged));
10012#endif
10013 return rcStrict;
10014}
10015
10016
10017/**
10018 * Tries to determine what part of the guest-state VT-x has deemed as invalid
10019 * and update error record fields accordingly.
10020 *
10021 * @returns VMX_IGS_* error codes.
10022 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
10023 * wrong with the guest state.
10024 *
10025 * @param pVCpu The cross context virtual CPU structure.
10026 * @param pVmcsInfo The VMCS info. object.
10027 *
10028 * @remarks This function assumes our cache of the VMCS controls
10029 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
10030 */
10031static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10032{
10033#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
10034#define HMVMX_CHECK_BREAK(expr, err) do { \
10035 if (!(expr)) { uError = (err); break; } \
10036 } while (0)
10037
10038 int rc;
10039 PVM pVM = pVCpu->CTX_SUFF(pVM);
10040 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
10041 uint32_t uError = VMX_IGS_ERROR;
10042 uint32_t u32Val;
10043 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
10044
10045 do
10046 {
10047 /*
10048 * CR0.
10049 */
10050 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10051 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10052 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10053 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
10054 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
10055 if (fUnrestrictedGuest)
10056 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
10057
10058 uint32_t u32GuestCr0;
10059 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
10060 AssertRCBreak(rc);
10061 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
10062 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
10063 if ( !fUnrestrictedGuest
10064 && (u32GuestCr0 & X86_CR0_PG)
10065 && !(u32GuestCr0 & X86_CR0_PE))
10066 {
10067 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
10068 }
10069
10070 /*
10071 * CR4.
10072 */
10073 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10074 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10075 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10076
10077 uint32_t u32GuestCr4;
10078 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
10079 AssertRCBreak(rc);
10080 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
10081 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
10082
10083 /*
10084 * IA32_DEBUGCTL MSR.
10085 */
10086 uint64_t u64Val;
10087 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
10088 AssertRCBreak(rc);
10089 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10090 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
10091 {
10092 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
10093 }
10094 uint64_t u64DebugCtlMsr = u64Val;
10095
10096#ifdef VBOX_STRICT
10097 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
10098 AssertRCBreak(rc);
10099 Assert(u32Val == pVmcsInfo->u32EntryCtls);
10100#endif
10101 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
10102
10103 /*
10104 * RIP and RFLAGS.
10105 */
10106 uint32_t u32Eflags;
10107#if HC_ARCH_BITS == 64
10108 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10109 AssertRCBreak(rc);
10110 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10111 if ( !fLongModeGuest
10112 || !pCtx->cs.Attr.n.u1Long)
10113 {
10114 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10115 }
10116 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10117 * must be identical if the "IA-32e mode guest" VM-entry
10118 * control is 1 and CS.L is 1. No check applies if the
10119 * CPU supports 64 linear-address bits. */
10120
10121 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10122 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10123 AssertRCBreak(rc);
10124 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10125 VMX_IGS_RFLAGS_RESERVED);
10126 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10127 u32Eflags = u64Val;
10128#else
10129 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10130 AssertRCBreak(rc);
10131 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10132 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10133#endif
10134
10135 if ( fLongModeGuest
10136 || ( fUnrestrictedGuest
10137 && !(u32GuestCr0 & X86_CR0_PE)))
10138 {
10139 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10140 }
10141
10142 uint32_t u32EntryInfo;
10143 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10144 AssertRCBreak(rc);
10145 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10146 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10147
10148 /*
10149 * 64-bit checks.
10150 */
10151#if HC_ARCH_BITS == 64
10152 if (fLongModeGuest)
10153 {
10154 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10155 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10156 }
10157
10158 if ( !fLongModeGuest
10159 && (u32GuestCr4 & X86_CR4_PCIDE))
10160 {
10161 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10162 }
10163
10164 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10165 * 51:32 beyond the processor's physical-address width are 0. */
10166
10167 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10168 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10169 {
10170 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10171 }
10172
10173 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10174 AssertRCBreak(rc);
10175 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10176
10177 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10178 AssertRCBreak(rc);
10179 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10180#endif
10181
10182 /*
10183 * PERF_GLOBAL MSR.
10184 */
10185 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10186 {
10187 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10188 AssertRCBreak(rc);
10189 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10190 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10191 }
10192
10193 /*
10194 * PAT MSR.
10195 */
10196 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10197 {
10198 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10199 AssertRCBreak(rc);
10200 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10201 for (unsigned i = 0; i < 8; i++)
10202 {
10203 uint8_t u8Val = (u64Val & 0xff);
10204 if ( u8Val != 0 /* UC */
10205 && u8Val != 1 /* WC */
10206 && u8Val != 4 /* WT */
10207 && u8Val != 5 /* WP */
10208 && u8Val != 6 /* WB */
10209 && u8Val != 7 /* UC- */)
10210 {
10211 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10212 }
10213 u64Val >>= 8;
10214 }
10215 }
10216
10217 /*
10218 * EFER MSR.
10219 */
10220 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10221 {
10222 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10223 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10224 AssertRCBreak(rc);
10225 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10226 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10227 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10228 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10229 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10230 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10231 * iemVmxVmentryCheckGuestState(). */
10232 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10233 || !(u32GuestCr0 & X86_CR0_PG)
10234 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10235 VMX_IGS_EFER_LMA_LME_MISMATCH);
10236 }
10237
10238 /*
10239 * Segment registers.
10240 */
10241 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10242 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10243 if (!(u32Eflags & X86_EFL_VM))
10244 {
10245 /* CS */
10246 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10247 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10248 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10249 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10250 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10251 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10252 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10253 /* CS cannot be loaded with NULL in protected mode. */
10254 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10255 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10256 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10257 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10258 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10259 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10260 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10261 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10262 else
10263 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10264
10265 /* SS */
10266 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10267 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10268 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10269 if ( !(pCtx->cr0 & X86_CR0_PE)
10270 || pCtx->cs.Attr.n.u4Type == 3)
10271 {
10272 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10273 }
10274 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10275 {
10276 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10277 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10278 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10279 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10280 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10281 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10282 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10283 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10284 }
10285
10286 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10287 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10288 {
10289 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10290 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10291 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10292 || pCtx->ds.Attr.n.u4Type > 11
10293 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10294 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10295 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10296 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10297 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10298 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10299 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10300 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10301 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10302 }
10303 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10304 {
10305 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10306 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10307 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10308 || pCtx->es.Attr.n.u4Type > 11
10309 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10310 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10311 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10312 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10313 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10314 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10315 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10316 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10317 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10318 }
10319 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10320 {
10321 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10322 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10323 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10324 || pCtx->fs.Attr.n.u4Type > 11
10325 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10326 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10327 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10328 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10329 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10330 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10331 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10332 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10333 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10334 }
10335 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10336 {
10337 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10338 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10339 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10340 || pCtx->gs.Attr.n.u4Type > 11
10341 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10342 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10343 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10344 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10345 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10346 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10347 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10348 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10349 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10350 }
10351 /* 64-bit capable CPUs. */
10352#if HC_ARCH_BITS == 64
10353 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10354 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10355 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10356 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10357 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10358 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10359 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10360 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10361 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10362 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10363 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10364#endif
10365 }
10366 else
10367 {
10368 /* V86 mode checks. */
10369 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10370 if (pVmcsInfo->RealMode.fRealOnV86Active)
10371 {
10372 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10373 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10374 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10375 }
10376 else
10377 {
10378 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10379 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10380 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10381 }
10382
10383 /* CS */
10384 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10385 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10386 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10387 /* SS */
10388 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10389 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10390 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10391 /* DS */
10392 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10393 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10394 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10395 /* ES */
10396 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10397 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10398 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10399 /* FS */
10400 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10401 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10402 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10403 /* GS */
10404 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10405 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10406 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10407 /* 64-bit capable CPUs. */
10408#if HC_ARCH_BITS == 64
10409 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10410 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10411 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10412 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10413 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10414 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10415 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10416 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10417 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10418 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10419 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10420#endif
10421 }
10422
10423 /*
10424 * TR.
10425 */
10426 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10427 /* 64-bit capable CPUs. */
10428#if HC_ARCH_BITS == 64
10429 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10430#endif
10431 if (fLongModeGuest)
10432 {
10433 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10434 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10435 }
10436 else
10437 {
10438 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10439 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10440 VMX_IGS_TR_ATTR_TYPE_INVALID);
10441 }
10442 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10443 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10444 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10445 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10446 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10447 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10448 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10449 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10450
10451 /*
10452 * GDTR and IDTR.
10453 */
10454#if HC_ARCH_BITS == 64
10455 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10456 AssertRCBreak(rc);
10457 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10458
10459 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10460 AssertRCBreak(rc);
10461 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10462#endif
10463
10464 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10465 AssertRCBreak(rc);
10466 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10467
10468 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10469 AssertRCBreak(rc);
10470 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10471
10472 /*
10473 * Guest Non-Register State.
10474 */
10475 /* Activity State. */
10476 uint32_t u32ActivityState;
10477 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10478 AssertRCBreak(rc);
10479 HMVMX_CHECK_BREAK( !u32ActivityState
10480 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10481 VMX_IGS_ACTIVITY_STATE_INVALID);
10482 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10483 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10484 uint32_t u32IntrState;
10485 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10486 AssertRCBreak(rc);
10487 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10488 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10489 {
10490 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10491 }
10492
10493 /** @todo Activity state and injecting interrupts. Left as a todo since we
10494 * currently don't use activity states but ACTIVE. */
10495
10496 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10497 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10498
10499 /* Guest interruptibility-state. */
10500 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10501 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10502 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10503 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10504 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10505 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10506 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10507 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10508 {
10509 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10510 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10511 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10512 }
10513 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10514 {
10515 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10516 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10517 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10518 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10519 }
10520 /** @todo Assumes the processor is not in SMM. */
10521 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10522 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10523 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10524 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10525 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10526 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10527 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10528 {
10529 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10530 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10531 }
10532
10533 /* Pending debug exceptions. */
10534#if HC_ARCH_BITS == 64
10535 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10536 AssertRCBreak(rc);
10537 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10538 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10539 u32Val = u64Val; /* For pending debug exceptions checks below. */
10540#else
10541 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10542 AssertRCBreak(rc);
10543 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10544 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10545#endif
10546
10547 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10548 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10549 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10550 {
10551 if ( (u32Eflags & X86_EFL_TF)
10552 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10553 {
10554 /* Bit 14 is PendingDebug.BS. */
10555 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10556 }
10557 if ( !(u32Eflags & X86_EFL_TF)
10558 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10559 {
10560 /* Bit 14 is PendingDebug.BS. */
10561 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10562 }
10563 }
10564
10565 /* VMCS link pointer. */
10566 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10567 AssertRCBreak(rc);
10568 if (u64Val != UINT64_C(0xffffffffffffffff))
10569 {
10570 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10571 /** @todo Bits beyond the processor's physical-address width MBZ. */
10572 /** @todo SMM checks. */
10573 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10574 Assert(pVmcsInfo->pvShadowVmcs);
10575 VMXVMCSREVID VmcsRevId;
10576 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10577 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10578 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10579 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10580 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10581 }
10582
10583 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10584 * not using nested paging? */
10585 if ( pVM->hm.s.fNestedPaging
10586 && !fLongModeGuest
10587 && CPUMIsGuestInPAEModeEx(pCtx))
10588 {
10589 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10590 AssertRCBreak(rc);
10591 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10592
10593 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10594 AssertRCBreak(rc);
10595 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10596
10597 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10598 AssertRCBreak(rc);
10599 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10600
10601 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10602 AssertRCBreak(rc);
10603 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10604 }
10605
10606 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10607 if (uError == VMX_IGS_ERROR)
10608 uError = VMX_IGS_REASON_NOT_FOUND;
10609 } while (0);
10610
10611 pVCpu->hm.s.u32HMError = uError;
10612 return uError;
10613
10614#undef HMVMX_ERROR_BREAK
10615#undef HMVMX_CHECK_BREAK
10616}
10617
10618
10619/**
10620 * Map the APIC-access page for virtualizing APIC accesses.
10621 *
10622 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10623 * this not done as part of exporting guest state, see @bugref{8721}.
10624 *
10625 * @returns VBox status code.
10626 * @param pVCpu The cross context virtual CPU structure.
10627 */
10628static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10629{
10630 PVM pVM = pVCpu->CTX_SUFF(pVM);
10631 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10632
10633 Assert(PDMHasApic(pVM));
10634 Assert(u64MsrApicBase);
10635
10636 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10637 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10638
10639 /* Unalias the existing mapping. */
10640 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10641 AssertRCReturn(rc, rc);
10642
10643 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10644 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10645 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10646 AssertRCReturn(rc, rc);
10647
10648 /* Update the per-VCPU cache of the APIC base MSR. */
10649 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10650 return VINF_SUCCESS;
10651}
10652
10653
10654/**
10655 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10656 * CPU.
10657 *
10658 * @param idCpu The ID for the CPU the function is called on.
10659 * @param pvUser1 Null, not used.
10660 * @param pvUser2 Null, not used.
10661 */
10662static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10663{
10664 RT_NOREF3(idCpu, pvUser1, pvUser2);
10665 VMXDispatchHostNmi();
10666}
10667
10668
10669/**
10670 * Dispatching an NMI on the host CPU that received it.
10671 *
10672 * @returns VBox status code.
10673 * @param pVCpu The cross context virtual CPU structure.
10674 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10675 * executing when receiving the host NMI in VMX non-root
10676 * operation.
10677 */
10678static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10679{
10680 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
10681
10682 /*
10683 * We don't want to delay dispatching the NMI any more than we have to. However,
10684 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10685 * after executing guest or nested-guest code for the following reasons:
10686 *
10687 * - We would need to perform VMREADs with interrupts disabled and is orders of
10688 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
10689 * supported by the host hypervisor.
10690 *
10691 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10692 * longer period of time just for handling an edge case like host NMIs which do
10693 * not occur nearly as frequently as other VM-exits.
10694 *
10695 * Let's cover the most likely scenario first. Check if we are on the target CPU
10696 * and dispatch the NMI right away. This should be much faster than calling into
10697 * RTMpOnSpecific() machinery.
10698 */
10699 bool fDispatched = false;
10700 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10701 if (idCpu == RTMpCpuId())
10702 {
10703 VMXDispatchHostNmi();
10704 fDispatched = true;
10705 }
10706 ASMSetFlags(fEFlags);
10707 if (fDispatched)
10708 {
10709 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10710 return VINF_SUCCESS;
10711 }
10712
10713 /*
10714 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10715 * there should be no race or recursion even if we are unlucky enough to be preempted
10716 * (to the target CPU) without dispatching the host NMI above.
10717 */
10718 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10719 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10720}
10721
10722
10723#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10724/**
10725 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10726 * nested-guest using hardware-assisted VMX.
10727 *
10728 * @param pVCpu The cross context virtual CPU structure.
10729 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10730 * @param pVmcsInfoGst The guest VMCS info. object.
10731 */
10732static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10733{
10734 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10735 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10736 Assert(pu64MsrBitmap);
10737
10738 /*
10739 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10740 * MSR that is intercepted by the guest is also intercepted while executing the
10741 * nested-guest using hardware-assisted VMX.
10742 *
10743 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10744 * nested-guest VM-exit even if the outer guest is not intercepting some
10745 * MSRs. We cannot assume the caller has initialized the nested-guest
10746 * MSR bitmap in this case.
10747 *
10748 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10749 * each VM-entry, hence initializing it once per-VM while setting up the
10750 * nested-guest VMCS is not sufficient.
10751 */
10752 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10753 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10754 {
10755 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10756 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10757 Assert(pu64MsrBitmapNstGst);
10758 Assert(pu64MsrBitmapGst);
10759
10760 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10761 for (uint32_t i = 0; i < cFrags; i++)
10762 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10763 }
10764 else
10765 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10766}
10767
10768
10769/**
10770 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10771 * hardware-assisted VMX execution of the nested-guest.
10772 *
10773 * For a guest, we don't modify these controls once we set up the VMCS and hence
10774 * this function is never called.
10775 *
10776 * For nested-guests since the guest hypervisor provides these controls on every
10777 * nested-guest VM-entry and could potentially change them everytime we need to
10778 * merge them before every nested-guest VM-entry.
10779 *
10780 * @returns VBox status code.
10781 * @param pVCpu The cross context virtual CPU structure.
10782 */
10783static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10784{
10785 PVM pVM = pVCpu->CTX_SUFF(pVM);
10786 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10787 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10788 Assert(pVmcsNstGst);
10789
10790 /*
10791 * Merge the controls with the requirements of the guest VMCS.
10792 *
10793 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10794 * VMCS with the features supported by the physical CPU as it's already done by the
10795 * VMLAUNCH/VMRESUME instruction emulation.
10796 *
10797 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10798 * derived from the VMX features supported by the physical CPU.
10799 */
10800
10801 /* Pin-based VM-execution controls. */
10802 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10803
10804 /* Processor-based VM-execution controls. */
10805 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10806 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10807 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10808 | VMX_PROC_CTLS_USE_TPR_SHADOW
10809 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10810
10811 /* Secondary processor-based VM-execution controls. */
10812 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10813 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10814 | VMX_PROC_CTLS2_INVPCID
10815 | VMX_PROC_CTLS2_VMCS_SHADOWING
10816 | VMX_PROC_CTLS2_RDTSCP
10817 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10818 | VMX_PROC_CTLS2_APIC_REG_VIRT
10819 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10820 | VMX_PROC_CTLS2_VMFUNC));
10821
10822 /*
10823 * VM-entry controls:
10824 * These controls contains state that depends on the nested-guest state (primarily
10825 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10826 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10827 * properly continue executing the nested-guest if the EFER MSR changes but does not
10828 * cause a nested-guest VM-exits.
10829 *
10830 * VM-exit controls:
10831 * These controls specify the host state on return. We cannot use the controls from
10832 * the guest hypervisor state as is as it would contain the guest state rather than
10833 * the host state. Since the host state is subject to change (e.g. preemption, trips
10834 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10835 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10836 *
10837 * VM-entry MSR-load:
10838 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10839 * context by the VMLAUNCH/VMRESUME instruction emulation.
10840 *
10841 * VM-exit MSR-store:
10842 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10843 * back into the VM-exit MSR-store area.
10844 *
10845 * VM-exit MSR-load areas:
10846 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10847 * can entirely ignore what the guest hypervisor wants to load here.
10848 */
10849
10850 /*
10851 * Exception bitmap.
10852 *
10853 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10854 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10855 * code more flexible if intercepting exceptions become more dynamic in the future we do
10856 * it as part of exporting the nested-guest state.
10857 */
10858 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10859
10860 /*
10861 * CR0/CR4 guest/host mask.
10862 *
10863 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10864 * cause VM-exits, so we need to merge them here.
10865 */
10866 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10867 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10868
10869 /*
10870 * Page-fault error-code mask and match.
10871 *
10872 * Although we require unrestricted guest execution (and thereby nested-paging) for
10873 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10874 * normally intercept #PFs, it might intercept them for debugging purposes.
10875 *
10876 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10877 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10878 */
10879 uint32_t u32XcptPFMask;
10880 uint32_t u32XcptPFMatch;
10881 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10882 {
10883 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10884 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10885 }
10886 else
10887 {
10888 u32XcptPFMask = 0;
10889 u32XcptPFMatch = 0;
10890 }
10891
10892 /*
10893 * Pause-Loop exiting.
10894 */
10895 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10896 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10897
10898 /*
10899 * I/O Bitmap.
10900 *
10901 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10902 * intercept all I/O port accesses.
10903 */
10904 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10905
10906 /*
10907 * VMCS shadowing.
10908 *
10909 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10910 * enabled while executing the nested-guest.
10911 */
10912 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10913
10914 /*
10915 * APIC-access page.
10916 */
10917 RTHCPHYS HCPhysApicAccess;
10918 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10919 {
10920 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10921 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10922
10923 /** @todo NSTVMX: This is not really correct but currently is required to make
10924 * things work. We need to re-register the page handler when we fallback to
10925 * IEM execution of the nested-guest! */
10926 PGMHandlerPhysicalDeregister(pVM, GCPhysApicAccess);
10927
10928 void *pvPage;
10929 PGMPAGEMAPLOCK PgMapLockApicAccess;
10930 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgMapLockApicAccess);
10931 if (RT_SUCCESS(rc))
10932 {
10933 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10934 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10935
10936 /*
10937 * We can release the page lock here because the APIC-access page is never read or
10938 * written to but merely serves as a placeholder in the shadow/nested page tables
10939 * to cause VM-exits or re-direct the access to the virtual-APIC page.
10940 */
10941 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgMapLockApicAccess);
10942 }
10943 else
10944 return rc;
10945 }
10946 else
10947 HCPhysApicAccess = 0;
10948
10949 /*
10950 * Virtual-APIC page and TPR threshold.
10951 */
10952 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10953 RTHCPHYS HCPhysVirtApic;
10954 uint32_t u32TprThreshold;
10955 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10956 {
10957 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10958
10959 void *pvPage;
10960 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10961 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &pVCpu->hm.s.vmx.PgMapLockVirtApic);
10962 AssertRCReturn(rc, rc);
10963 if (RT_SUCCESS(rc))
10964 {
10965 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10966 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10967 pVCpu->hm.s.vmx.fVirtApicPageLocked = true;
10968 }
10969 else
10970 return rc;
10971 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10972 }
10973 else
10974 {
10975 HCPhysVirtApic = 0;
10976 u32TprThreshold = 0;
10977
10978 /*
10979 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10980 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10981 * be taken care of by EPT/shadow paging.
10982 */
10983 if (pVM->hm.s.fAllow64BitGuests)
10984 {
10985 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10986 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10987 }
10988 }
10989
10990 /*
10991 * Validate basic assumptions.
10992 */
10993 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10994 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10995 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10996
10997 /*
10998 * Commit it to the nested-guest VMCS.
10999 */
11000 int rc = VINF_SUCCESS;
11001 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
11002 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
11003 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
11004 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
11005 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
11006 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
11007 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
11008 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
11009 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
11010 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
11011 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
11012 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
11013 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
11014 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
11015 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
11016 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
11017 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
11018 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
11019 {
11020 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
11021 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
11022 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
11023 }
11024 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11025 {
11026 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
11027 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
11028 }
11029 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
11030 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
11031 AssertRCReturn(rc, rc);
11032
11033 /*
11034 * Update the nested-guest VMCS cache.
11035 */
11036 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
11037 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
11038 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
11039 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
11040 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
11041 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
11042 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
11043 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
11044 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
11045
11046 /*
11047 * We need to flush the TLB if we are switching the APIC-access page address.
11048 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
11049 */
11050 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
11051 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
11052
11053 /*
11054 * MSR bitmap.
11055 *
11056 * The MSR bitmap address has already been initialized while setting up the nested-guest
11057 * VMCS, here we need to merge the MSR bitmaps.
11058 */
11059 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
11060 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
11061
11062 return VINF_SUCCESS;
11063}
11064#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11065
11066
11067/**
11068 * Does the preparations before executing guest code in VT-x.
11069 *
11070 * This may cause longjmps to ring-3 and may even result in rescheduling to the
11071 * recompiler/IEM. We must be cautious what we do here regarding committing
11072 * guest-state information into the VMCS assuming we assuredly execute the
11073 * guest in VT-x mode.
11074 *
11075 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
11076 * the common-state (TRPM/forceflags), we must undo those changes so that the
11077 * recompiler/IEM can (and should) use them when it resumes guest execution.
11078 * Otherwise such operations must be done when we can no longer exit to ring-3.
11079 *
11080 * @returns Strict VBox status code (i.e. informational status codes too).
11081 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
11082 * have been disabled.
11083 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
11084 * pending events).
11085 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
11086 * double-fault into the guest.
11087 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
11088 * dispatched directly.
11089 * @retval VINF_* scheduling changes, we have to go back to ring-3.
11090 *
11091 * @param pVCpu The cross context virtual CPU structure.
11092 * @param pVmxTransient The VMX-transient structure.
11093 * @param fStepping Whether we are single-stepping the guest in the
11094 * hypervisor debugger. Makes us ignore some of the reasons
11095 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
11096 * if event dispatching took place.
11097 */
11098static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
11099{
11100 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11101
11102#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
11103 if (pVmxTransient->fIsNestedGuest)
11104 {
11105 RT_NOREF2(pVCpu, fStepping);
11106 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
11107 return VINF_EM_RESCHEDULE_REM;
11108 }
11109#endif
11110
11111#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
11112 PGMRZDynMapFlushAutoSet(pVCpu);
11113#endif
11114
11115 /*
11116 * Check and process force flag actions, some of which might require us to go back to ring-3.
11117 */
11118 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
11119 if (rcStrict == VINF_SUCCESS)
11120 { /* FFs don't get set all the time. */ }
11121 else
11122 return rcStrict;
11123
11124 /*
11125 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
11126 */
11127 /** @todo Doing this from ring-3 after VM setup phase causes a
11128 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
11129 * idea why atm. */
11130 PVM pVM = pVCpu->CTX_SUFF(pVM);
11131 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
11132 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
11133 && PDMHasApic(pVM))
11134 {
11135 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
11136 AssertRCReturn(rc, rc);
11137 }
11138
11139#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11140 /*
11141 * Merge guest VMCS controls with the nested-guest VMCS controls.
11142 *
11143 * Even if we have not executed the guest prior to this (e.g. when resuming from a
11144 * saved state), we should be okay with merging controls as we initialize the
11145 * guest VMCS controls as part of VM setup phase.
11146 */
11147 if ( pVmxTransient->fIsNestedGuest
11148 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
11149 {
11150 int rc = hmR0VmxMergeVmcsNested(pVCpu);
11151 AssertRCReturn(rc, rc);
11152 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
11153 }
11154#endif
11155
11156 /*
11157 * Evaluate events to be injected into the guest.
11158 *
11159 * Events in TRPM can be injected without inspecting the guest state.
11160 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11161 * guest to cause a VM-exit the next time they are ready to receive the event.
11162 *
11163 * With nested-guests, evaluating pending events may cause VM-exits.
11164 */
11165 if (TRPMHasTrap(pVCpu))
11166 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11167
11168 uint32_t fIntrState;
11169 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11170
11171#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11172 /*
11173 * While evaluating pending events if something failed (unlikely) or if we were
11174 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11175 */
11176 if (rcStrict != VINF_SUCCESS)
11177 return rcStrict;
11178 if ( pVmxTransient->fIsNestedGuest
11179 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11180 {
11181 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11182 return VINF_VMX_VMEXIT;
11183 }
11184#else
11185 Assert(rcStrict == VINF_SUCCESS);
11186#endif
11187
11188 /*
11189 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11190 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11191 * also result in triple-faulting the VM.
11192 *
11193 * With nested-guests, the above does not apply since unrestricted guest execution is a
11194 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11195 */
11196 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11197 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11198 { /* likely */ }
11199 else
11200 {
11201 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11202 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11203 return rcStrict;
11204 }
11205
11206 /*
11207 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11208 * import CR3 themselves. We will need to update them here, as even as late as the above
11209 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11210 * the below force flags to be set.
11211 */
11212 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11213 {
11214 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11215 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11216 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11217 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11218 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11219 }
11220 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11221 {
11222 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11223 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11224 }
11225
11226#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11227 /* Paranoia. */
11228 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11229#endif
11230
11231 /*
11232 * No longjmps to ring-3 from this point on!!!
11233 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11234 * This also disables flushing of the R0-logger instance (if any).
11235 */
11236 VMMRZCallRing3Disable(pVCpu);
11237
11238 /*
11239 * Export the guest state bits.
11240 *
11241 * We cannot perform longjmps while loading the guest state because we do not preserve the
11242 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11243 * CPU migration.
11244 *
11245 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11246 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11247 */
11248 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11249 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11250 { /* likely */ }
11251 else
11252 {
11253 VMMRZCallRing3Enable(pVCpu);
11254 return rcStrict;
11255 }
11256
11257 /*
11258 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11259 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11260 * preemption disabled for a while. Since this is purely to aid the
11261 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11262 * disable interrupt on NT.
11263 *
11264 * We need to check for force-flags that could've possible been altered since we last
11265 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11266 * see @bugref{6398}).
11267 *
11268 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11269 * to ring-3 before executing guest code.
11270 */
11271 pVmxTransient->fEFlags = ASMIntDisableFlags();
11272
11273 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11274 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11275 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11276 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11277 {
11278 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11279 {
11280#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11281 /*
11282 * If we are executing a nested-guest make sure that we should intercept subsequent
11283 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
11284 * the VM-exit instruction emulation happy.
11285 */
11286 if (pVmxTransient->fIsNestedGuest)
11287 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11288#endif
11289
11290 /*
11291 * We've injected any pending events. This is really the point of no return (to ring-3).
11292 *
11293 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11294 * returns from this function, so do -not- enable them here.
11295 */
11296 pVCpu->hm.s.Event.fPending = false;
11297 return VINF_SUCCESS;
11298 }
11299
11300 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11301 rcStrict = VINF_EM_RAW_INTERRUPT;
11302 }
11303 else
11304 {
11305 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11306 rcStrict = VINF_EM_RAW_TO_R3;
11307 }
11308
11309 ASMSetFlags(pVmxTransient->fEFlags);
11310 VMMRZCallRing3Enable(pVCpu);
11311
11312 return rcStrict;
11313}
11314
11315
11316/**
11317 * Final preparations before executing guest code using hardware-assisted VMX.
11318 *
11319 * We can no longer get preempted to a different host CPU and there are no returns
11320 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11321 * failures), this function is not intended to fail sans unrecoverable hardware
11322 * errors.
11323 *
11324 * @param pVCpu The cross context virtual CPU structure.
11325 * @param pVmxTransient The VMX-transient structure.
11326 *
11327 * @remarks Called with preemption disabled.
11328 * @remarks No-long-jump zone!!!
11329 */
11330static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11331{
11332 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11333 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11334 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11335 Assert(!pVCpu->hm.s.Event.fPending);
11336
11337 /*
11338 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11339 */
11340 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11341 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11342
11343 PVM pVM = pVCpu->CTX_SUFF(pVM);
11344 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11345 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11346 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11347
11348 if (!CPUMIsGuestFPUStateActive(pVCpu))
11349 {
11350 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11351 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11352 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11353 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11354 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11355 }
11356
11357 /*
11358 * Re-export the host state bits as we may've been preempted (only happens when
11359 * thread-context hooks are used or when the VM start function changes) or if
11360 * the host CR0 is modified while loading the guest FPU state above.
11361 *
11362 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11363 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11364 * see @bugref{8432}.
11365 *
11366 * This may also happen when switching to/from a nested-guest VMCS without leaving
11367 * ring-0.
11368 */
11369 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11370 {
11371 hmR0VmxExportHostState(pVCpu);
11372 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11373 }
11374 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11375
11376 /*
11377 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11378 */
11379 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11380 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11381 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11382
11383 /*
11384 * Store status of the shared guest/host debug state at the time of VM-entry.
11385 */
11386#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11387 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11388 {
11389 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11390 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11391 }
11392 else
11393#endif
11394 {
11395 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11396 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11397 }
11398
11399 /*
11400 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11401 * more than one conditional check. The post-run side of our code shall determine
11402 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11403 */
11404 if (pVmcsInfo->pbVirtApic)
11405 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11406
11407 /*
11408 * Update the host MSRs values in the VM-exit MSR-load area.
11409 */
11410 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11411 {
11412 if (pVmcsInfo->cExitMsrLoad > 0)
11413 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11414 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11415 }
11416
11417 /*
11418 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11419 * VMX-preemption timer based on the next virtual sync clock deadline.
11420 */
11421 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11422 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11423 {
11424 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11425 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11426 }
11427
11428 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11429 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11430 if (!fIsRdtscIntercepted)
11431 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11432 else
11433 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11434
11435 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11436 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11437 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11438 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11439 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11440
11441 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11442
11443 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11444 as we're about to start executing the guest . */
11445
11446 /*
11447 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11448 *
11449 * This is done this late as updating the TSC offsetting/preemption timer above
11450 * figures out if we can skip intercepting RDTSCP by calculating the number of
11451 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11452 */
11453 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11454 && !fIsRdtscIntercepted)
11455 {
11456 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11457
11458 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11459 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11460 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11461 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11462 AssertRC(rc);
11463 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11464 pVmxTransient->fRemoveTscAuxMsr = true;
11465 }
11466
11467#ifdef VBOX_STRICT
11468 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11469 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11470 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11471 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11472#endif
11473
11474#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11475 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11476 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11477 * see @bugref{9180#c54}. */
11478 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11479 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11480 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11481#endif
11482}
11483
11484
11485/**
11486 * First C routine invoked after running guest code using hardware-assisted VMX.
11487 *
11488 * @param pVCpu The cross context virtual CPU structure.
11489 * @param pVmxTransient The VMX-transient structure.
11490 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11491 *
11492 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11493 *
11494 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11495 * unconditionally when it is safe to do so.
11496 */
11497static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11498{
11499 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11500
11501 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11502 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11503 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11504 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11505 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11506 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11507
11508 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11509 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11510 {
11511 uint64_t uGstTsc;
11512 if (!pVmxTransient->fIsNestedGuest)
11513 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11514 else
11515 {
11516 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11517 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11518 }
11519 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11520 }
11521
11522 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11523 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11524 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11525
11526#if HC_ARCH_BITS == 64
11527 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11528#endif
11529#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11530 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11531 and we need to leave it alone here. */
11532 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11533 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11534#else
11535 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11536#endif
11537#ifdef VBOX_STRICT
11538 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11539#endif
11540 Assert(!ASMIntAreEnabled());
11541 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11542 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11543
11544#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11545 /*
11546 * Clean all the VMCS fields in the transient structure before reading
11547 * anything from the VMCS.
11548 */
11549 pVmxTransient->uExitReason = 0;
11550 pVmxTransient->uExitIntErrorCode = 0;
11551 pVmxTransient->uExitQual = 0;
11552 pVmxTransient->uGuestLinearAddr = 0;
11553 pVmxTransient->uExitIntInfo = 0;
11554 pVmxTransient->cbInstr = 0;
11555 pVmxTransient->ExitInstrInfo.u = 0;
11556 pVmxTransient->uEntryIntInfo = 0;
11557 pVmxTransient->uEntryXcptErrorCode = 0;
11558 pVmxTransient->cbEntryInstr = 0;
11559 pVmxTransient->uIdtVectoringInfo = 0;
11560 pVmxTransient->uIdtVectoringErrorCode = 0;
11561#endif
11562
11563 /*
11564 * Save the basic VM-exit reason and check if the VM-entry failed.
11565 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11566 */
11567 uint32_t uExitReason;
11568 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11569 AssertRC(rc);
11570 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11571 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11572
11573 /*
11574 * Log the VM-exit before logging anything else as otherwise it might be a
11575 * tad confusing what happens before and after the world-switch.
11576 */
11577 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11578
11579 /*
11580 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11581 * bitmap permissions, if it was added before VM-entry.
11582 */
11583 if (pVmxTransient->fRemoveTscAuxMsr)
11584 {
11585 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11586 pVmxTransient->fRemoveTscAuxMsr = false;
11587 }
11588
11589 /*
11590 * Check if VMLAUNCH/VMRESUME succeeded.
11591 * If this failed, we cause a guru meditation and cease further execution.
11592 *
11593 * However, if we are executing a nested-guest we might fail if we use the
11594 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11595 */
11596 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11597 {
11598 /*
11599 * Update the VM-exit history array here even if the VM-entry failed due to:
11600 * - Invalid guest state.
11601 * - MSR loading.
11602 * - Machine-check event.
11603 *
11604 * In any of the above cases we will still have a "valid" VM-exit reason
11605 * despite @a fVMEntryFailed being false.
11606 *
11607 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11608 *
11609 * Note! We don't have CS or RIP at this point. Will probably address that later
11610 * by amending the history entry added here.
11611 */
11612 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11613 UINT64_MAX, uHostTsc);
11614
11615 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11616 {
11617 VMMRZCallRing3Enable(pVCpu);
11618
11619 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11620 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11621
11622#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
11623 rc = hmR0VmxReadAllRoFieldsVmcs(pVCpu, pVmxTransient);
11624 AssertRC(rc);
11625#endif
11626#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11627 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11628 AssertRC(rc);
11629#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11630 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11631 AssertRC(rc);
11632#else
11633 /*
11634 * Import the guest-interruptibility state always as we need it while evaluating
11635 * injecting events on re-entry.
11636 *
11637 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11638 * checking for real-mode while exporting the state because all bits that cause
11639 * mode changes wrt CR0 are intercepted.
11640 */
11641 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11642 AssertRC(rc);
11643#endif
11644
11645 /*
11646 * Sync the TPR shadow with our APIC state.
11647 */
11648 if ( !pVmxTransient->fIsNestedGuest
11649 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
11650 {
11651 Assert(pVmcsInfo->pbVirtApic);
11652 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11653 {
11654 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11655 AssertRC(rc);
11656 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11657 }
11658 }
11659
11660 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11661 return;
11662 }
11663 }
11664#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11665 else if (pVmxTransient->fIsNestedGuest)
11666 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11667#endif
11668 else
11669 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11670
11671 VMMRZCallRing3Enable(pVCpu);
11672}
11673
11674
11675/**
11676 * Runs the guest code using hardware-assisted VMX the normal way.
11677 *
11678 * @returns VBox status code.
11679 * @param pVCpu The cross context virtual CPU structure.
11680 * @param pcLoops Pointer to the number of executed loops.
11681 */
11682static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11683{
11684 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11685 Assert(pcLoops);
11686 Assert(*pcLoops <= cMaxResumeLoops);
11687 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11688
11689#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11690 /*
11691 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11692 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11693 * guest VMCS while entering the VMX ring-0 session.
11694 */
11695 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11696 {
11697 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11698 if (RT_SUCCESS(rc))
11699 { /* likely */ }
11700 else
11701 {
11702 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11703 return rc;
11704 }
11705 }
11706#endif
11707
11708 VMXTRANSIENT VmxTransient;
11709 RT_ZERO(VmxTransient);
11710 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11711
11712 /* Paranoia. */
11713 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11714
11715 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11716 for (;;)
11717 {
11718 Assert(!HMR0SuspendPending());
11719 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11720 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11721
11722 /*
11723 * Preparatory work for running nested-guest code, this may force us to
11724 * return to ring-3.
11725 *
11726 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11727 */
11728 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11729 if (rcStrict != VINF_SUCCESS)
11730 break;
11731
11732 /* Interrupts are disabled at this point! */
11733 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11734 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11735 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11736 /* Interrupts are re-enabled at this point! */
11737
11738 /*
11739 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11740 */
11741 if (RT_SUCCESS(rcRun))
11742 { /* very likely */ }
11743 else
11744 {
11745 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11746 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11747 return rcRun;
11748 }
11749
11750 /*
11751 * Profile the VM-exit.
11752 */
11753 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11754 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11755 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11756 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11757 HMVMX_START_EXIT_DISPATCH_PROF();
11758
11759 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11760
11761 /*
11762 * Handle the VM-exit.
11763 */
11764#ifdef HMVMX_USE_FUNCTION_TABLE
11765 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11766#else
11767 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11768#endif
11769 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11770 if (rcStrict == VINF_SUCCESS)
11771 {
11772 if (++(*pcLoops) <= cMaxResumeLoops)
11773 continue;
11774 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11775 rcStrict = VINF_EM_RAW_INTERRUPT;
11776 }
11777 break;
11778 }
11779
11780 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11781 return rcStrict;
11782}
11783
11784
11785#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11786/**
11787 * Runs the nested-guest code using hardware-assisted VMX.
11788 *
11789 * @returns VBox status code.
11790 * @param pVCpu The cross context virtual CPU structure.
11791 * @param pcLoops Pointer to the number of executed loops.
11792 *
11793 * @sa hmR0VmxRunGuestCodeNormal.
11794 */
11795static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11796{
11797 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11798 Assert(pcLoops);
11799 Assert(*pcLoops <= cMaxResumeLoops);
11800 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11801
11802 /*
11803 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11804 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11805 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11806 */
11807 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11808 {
11809 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11810 if (RT_SUCCESS(rc))
11811 { /* likely */ }
11812 else
11813 {
11814 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11815 return rc;
11816 }
11817 }
11818
11819 VMXTRANSIENT VmxTransient;
11820 RT_ZERO(VmxTransient);
11821 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11822 VmxTransient.fIsNestedGuest = true;
11823
11824 /* Paranoia. */
11825 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11826
11827 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11828 for (;;)
11829 {
11830 Assert(!HMR0SuspendPending());
11831 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11832 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11833
11834 /*
11835 * Preparatory work for running guest code, this may force us to
11836 * return to ring-3.
11837 *
11838 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11839 */
11840 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11841 if (rcStrict != VINF_SUCCESS)
11842 break;
11843
11844 /* Interrupts are disabled at this point! */
11845 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11846 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11847 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11848 /* Interrupts are re-enabled at this point! */
11849
11850 /*
11851 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11852 */
11853 if (RT_SUCCESS(rcRun))
11854 { /* very likely */ }
11855 else
11856 {
11857 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11858 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11859 return rcRun;
11860 }
11861
11862 /*
11863 * Profile the VM-exit.
11864 */
11865 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11866 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11867 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11868 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11869 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11870 HMVMX_START_EXIT_DISPATCH_PROF();
11871
11872 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11873
11874 /*
11875 * Handle the VM-exit.
11876 */
11877 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11878 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11879 if (rcStrict == VINF_SUCCESS)
11880 {
11881 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11882 {
11883 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11884 rcStrict = VINF_VMX_VMEXIT;
11885 }
11886 else
11887 {
11888 if (++(*pcLoops) <= cMaxResumeLoops)
11889 continue;
11890 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11891 rcStrict = VINF_EM_RAW_INTERRUPT;
11892 }
11893 }
11894 else
11895 Assert(rcStrict != VINF_VMX_VMEXIT);
11896 break;
11897 }
11898
11899 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11900 return rcStrict;
11901}
11902#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11903
11904
11905/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11906 * probes.
11907 *
11908 * The following few functions and associated structure contains the bloat
11909 * necessary for providing detailed debug events and dtrace probes as well as
11910 * reliable host side single stepping. This works on the principle of
11911 * "subclassing" the normal execution loop and workers. We replace the loop
11912 * method completely and override selected helpers to add necessary adjustments
11913 * to their core operation.
11914 *
11915 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11916 * any performance for debug and analysis features.
11917 *
11918 * @{
11919 */
11920
11921/**
11922 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11923 * the debug run loop.
11924 */
11925typedef struct VMXRUNDBGSTATE
11926{
11927 /** The RIP we started executing at. This is for detecting that we stepped. */
11928 uint64_t uRipStart;
11929 /** The CS we started executing with. */
11930 uint16_t uCsStart;
11931
11932 /** Whether we've actually modified the 1st execution control field. */
11933 bool fModifiedProcCtls : 1;
11934 /** Whether we've actually modified the 2nd execution control field. */
11935 bool fModifiedProcCtls2 : 1;
11936 /** Whether we've actually modified the exception bitmap. */
11937 bool fModifiedXcptBitmap : 1;
11938
11939 /** We desire the modified the CR0 mask to be cleared. */
11940 bool fClearCr0Mask : 1;
11941 /** We desire the modified the CR4 mask to be cleared. */
11942 bool fClearCr4Mask : 1;
11943 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11944 uint32_t fCpe1Extra;
11945 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11946 uint32_t fCpe1Unwanted;
11947 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11948 uint32_t fCpe2Extra;
11949 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11950 uint32_t bmXcptExtra;
11951 /** The sequence number of the Dtrace provider settings the state was
11952 * configured against. */
11953 uint32_t uDtraceSettingsSeqNo;
11954 /** VM-exits to check (one bit per VM-exit). */
11955 uint32_t bmExitsToCheck[3];
11956
11957 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11958 uint32_t fProcCtlsInitial;
11959 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11960 uint32_t fProcCtls2Initial;
11961 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11962 uint32_t bmXcptInitial;
11963} VMXRUNDBGSTATE;
11964AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11965typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11966
11967
11968/**
11969 * Initializes the VMXRUNDBGSTATE structure.
11970 *
11971 * @param pVCpu The cross context virtual CPU structure of the
11972 * calling EMT.
11973 * @param pVmxTransient The VMX-transient structure.
11974 * @param pDbgState The debug state to initialize.
11975 */
11976static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11977{
11978 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11979 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11980
11981 pDbgState->fModifiedProcCtls = false;
11982 pDbgState->fModifiedProcCtls2 = false;
11983 pDbgState->fModifiedXcptBitmap = false;
11984 pDbgState->fClearCr0Mask = false;
11985 pDbgState->fClearCr4Mask = false;
11986 pDbgState->fCpe1Extra = 0;
11987 pDbgState->fCpe1Unwanted = 0;
11988 pDbgState->fCpe2Extra = 0;
11989 pDbgState->bmXcptExtra = 0;
11990 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11991 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11992 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11993}
11994
11995
11996/**
11997 * Updates the VMSC fields with changes requested by @a pDbgState.
11998 *
11999 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
12000 * immediately before executing guest code, i.e. when interrupts are disabled.
12001 * We don't check status codes here as we cannot easily assert or return in the
12002 * latter case.
12003 *
12004 * @param pVCpu The cross context virtual CPU structure.
12005 * @param pVmxTransient The VMX-transient structure.
12006 * @param pDbgState The debug state.
12007 */
12008static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12009{
12010 /*
12011 * Ensure desired flags in VMCS control fields are set.
12012 * (Ignoring write failure here, as we're committed and it's just debug extras.)
12013 *
12014 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
12015 * there should be no stale data in pCtx at this point.
12016 */
12017 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12018 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
12019 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
12020 {
12021 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
12022 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
12023 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
12024 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
12025 pDbgState->fModifiedProcCtls = true;
12026 }
12027
12028 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
12029 {
12030 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
12031 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
12032 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
12033 pDbgState->fModifiedProcCtls2 = true;
12034 }
12035
12036 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
12037 {
12038 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
12039 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
12040 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
12041 pDbgState->fModifiedXcptBitmap = true;
12042 }
12043
12044 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
12045 {
12046 pVmcsInfo->u64Cr0Mask = 0;
12047 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
12048 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
12049 }
12050
12051 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
12052 {
12053 pVmcsInfo->u64Cr4Mask = 0;
12054 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
12055 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
12056 }
12057
12058 NOREF(pVCpu);
12059}
12060
12061
12062/**
12063 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
12064 * re-entry next time around.
12065 *
12066 * @returns Strict VBox status code (i.e. informational status codes too).
12067 * @param pVCpu The cross context virtual CPU structure.
12068 * @param pVmxTransient The VMX-transient structure.
12069 * @param pDbgState The debug state.
12070 * @param rcStrict The return code from executing the guest using single
12071 * stepping.
12072 */
12073static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
12074 VBOXSTRICTRC rcStrict)
12075{
12076 /*
12077 * Restore VM-exit control settings as we may not reenter this function the
12078 * next time around.
12079 */
12080 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12081
12082 /* We reload the initial value, trigger what we can of recalculations the
12083 next time around. From the looks of things, that's all that's required atm. */
12084 if (pDbgState->fModifiedProcCtls)
12085 {
12086 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
12087 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
12088 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
12089 AssertRCReturn(rc2, rc2);
12090 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
12091 }
12092
12093 /* We're currently the only ones messing with this one, so just restore the
12094 cached value and reload the field. */
12095 if ( pDbgState->fModifiedProcCtls2
12096 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
12097 {
12098 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
12099 AssertRCReturn(rc2, rc2);
12100 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
12101 }
12102
12103 /* If we've modified the exception bitmap, we restore it and trigger
12104 reloading and partial recalculation the next time around. */
12105 if (pDbgState->fModifiedXcptBitmap)
12106 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
12107
12108 return rcStrict;
12109}
12110
12111
12112/**
12113 * Configures VM-exit controls for current DBGF and DTrace settings.
12114 *
12115 * This updates @a pDbgState and the VMCS execution control fields to reflect
12116 * the necessary VM-exits demanded by DBGF and DTrace.
12117 *
12118 * @param pVCpu The cross context virtual CPU structure.
12119 * @param pVmxTransient The VMX-transient structure. May update
12120 * fUpdatedTscOffsettingAndPreemptTimer.
12121 * @param pDbgState The debug state.
12122 */
12123static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12124{
12125 /*
12126 * Take down the dtrace serial number so we can spot changes.
12127 */
12128 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
12129 ASMCompilerBarrier();
12130
12131 /*
12132 * We'll rebuild most of the middle block of data members (holding the
12133 * current settings) as we go along here, so start by clearing it all.
12134 */
12135 pDbgState->bmXcptExtra = 0;
12136 pDbgState->fCpe1Extra = 0;
12137 pDbgState->fCpe1Unwanted = 0;
12138 pDbgState->fCpe2Extra = 0;
12139 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
12140 pDbgState->bmExitsToCheck[i] = 0;
12141
12142 /*
12143 * Software interrupts (INT XXh) - no idea how to trigger these...
12144 */
12145 PVM pVM = pVCpu->CTX_SUFF(pVM);
12146 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
12147 || VBOXVMM_INT_SOFTWARE_ENABLED())
12148 {
12149 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12150 }
12151
12152 /*
12153 * INT3 breakpoints - triggered by #BP exceptions.
12154 */
12155 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
12156 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12157
12158 /*
12159 * Exception bitmap and XCPT events+probes.
12160 */
12161 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
12162 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
12163 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
12164
12165 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
12166 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
12167 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12168 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
12169 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
12170 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
12171 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12172 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12173 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12174 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12175 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12176 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12177 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12178 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12179 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12180 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12181 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12182 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12183
12184 if (pDbgState->bmXcptExtra)
12185 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12186
12187 /*
12188 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12189 *
12190 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12191 * So, when adding/changing/removing please don't forget to update it.
12192 *
12193 * Some of the macros are picking up local variables to save horizontal space,
12194 * (being able to see it in a table is the lesser evil here).
12195 */
12196#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12197 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12198 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12199#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12200 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12201 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12202 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12203 } else do { } while (0)
12204#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12205 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12206 { \
12207 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12208 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12209 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12210 } else do { } while (0)
12211#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12212 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12213 { \
12214 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12215 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12216 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12217 } else do { } while (0)
12218#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12219 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12220 { \
12221 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12222 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12223 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12224 } else do { } while (0)
12225
12226 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12227 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12228 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12229 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12230 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12231
12232 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12233 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12234 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12235 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12236 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12237 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12238 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12239 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12240 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12241 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12242 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12243 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12244 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12245 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12246 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12247 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12248 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12249 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12250 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12251 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12252 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12253 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12254 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12255 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12256 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12257 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12258 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12259 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12260 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12261 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12262 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12263 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12264 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12265 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12266 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12267 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12268
12269 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12270 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12271 {
12272 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12273 | CPUMCTX_EXTRN_APIC_TPR);
12274 AssertRC(rc);
12275
12276#if 0 /** @todo fix me */
12277 pDbgState->fClearCr0Mask = true;
12278 pDbgState->fClearCr4Mask = true;
12279#endif
12280 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12281 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12282 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12283 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12284 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12285 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12286 require clearing here and in the loop if we start using it. */
12287 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12288 }
12289 else
12290 {
12291 if (pDbgState->fClearCr0Mask)
12292 {
12293 pDbgState->fClearCr0Mask = false;
12294 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12295 }
12296 if (pDbgState->fClearCr4Mask)
12297 {
12298 pDbgState->fClearCr4Mask = false;
12299 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12300 }
12301 }
12302 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12303 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12304
12305 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12306 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12307 {
12308 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12309 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12310 }
12311 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12312 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12313
12314 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12315 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12316 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12317 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12318 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12319 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12320 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12321 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12322#if 0 /** @todo too slow, fix handler. */
12323 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12324#endif
12325 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12326
12327 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12328 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12329 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12330 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12331 {
12332 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12333 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12334 }
12335 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12336 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12337 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12338 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12339
12340 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12341 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12342 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12343 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12344 {
12345 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12346 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12347 }
12348 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12349 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12350 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12351 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12352
12353 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12354 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12355 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12356 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12357 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12358 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12359 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12360 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12361 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12362 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12363 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12364 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12365 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12366 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12367 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12368 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12369 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12370 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12371 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12372 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12373 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12374 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12375
12376#undef IS_EITHER_ENABLED
12377#undef SET_ONLY_XBM_IF_EITHER_EN
12378#undef SET_CPE1_XBM_IF_EITHER_EN
12379#undef SET_CPEU_XBM_IF_EITHER_EN
12380#undef SET_CPE2_XBM_IF_EITHER_EN
12381
12382 /*
12383 * Sanitize the control stuff.
12384 */
12385 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12386 if (pDbgState->fCpe2Extra)
12387 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12388 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12389 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12390 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12391 {
12392 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12393 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12394 }
12395
12396 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12397 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12398 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12399 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12400}
12401
12402
12403/**
12404 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12405 * appropriate.
12406 *
12407 * The caller has checked the VM-exit against the
12408 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12409 * already, so we don't have to do that either.
12410 *
12411 * @returns Strict VBox status code (i.e. informational status codes too).
12412 * @param pVCpu The cross context virtual CPU structure.
12413 * @param pVmxTransient The VMX-transient structure.
12414 * @param uExitReason The VM-exit reason.
12415 *
12416 * @remarks The name of this function is displayed by dtrace, so keep it short
12417 * and to the point. No longer than 33 chars long, please.
12418 */
12419static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12420{
12421 /*
12422 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12423 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12424 *
12425 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12426 * does. Must add/change/remove both places. Same ordering, please.
12427 *
12428 * Added/removed events must also be reflected in the next section
12429 * where we dispatch dtrace events.
12430 */
12431 bool fDtrace1 = false;
12432 bool fDtrace2 = false;
12433 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12434 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12435 uint32_t uEventArg = 0;
12436#define SET_EXIT(a_EventSubName) \
12437 do { \
12438 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12439 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12440 } while (0)
12441#define SET_BOTH(a_EventSubName) \
12442 do { \
12443 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12444 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12445 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12446 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12447 } while (0)
12448 switch (uExitReason)
12449 {
12450 case VMX_EXIT_MTF:
12451 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12452
12453 case VMX_EXIT_XCPT_OR_NMI:
12454 {
12455 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12456 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12457 {
12458 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12459 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12460 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12461 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12462 {
12463 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12464 {
12465 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12466 uEventArg = pVmxTransient->uExitIntErrorCode;
12467 }
12468 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12469 switch (enmEvent1)
12470 {
12471 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12472 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12473 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12474 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12475 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12476 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12477 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12478 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12479 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12480 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12481 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12482 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12483 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12484 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12485 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12486 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12487 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12488 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12489 default: break;
12490 }
12491 }
12492 else
12493 AssertFailed();
12494 break;
12495
12496 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12497 uEventArg = idxVector;
12498 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12499 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12500 break;
12501 }
12502 break;
12503 }
12504
12505 case VMX_EXIT_TRIPLE_FAULT:
12506 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12507 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12508 break;
12509 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12510 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12511 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12512 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12513 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12514
12515 /* Instruction specific VM-exits: */
12516 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12517 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12518 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12519 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12520 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12521 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12522 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12523 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12524 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12525 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12526 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12527 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12528 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12529 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12530 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12531 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12532 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12533 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12534 case VMX_EXIT_MOV_CRX:
12535 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12536 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12537 SET_BOTH(CRX_READ);
12538 else
12539 SET_BOTH(CRX_WRITE);
12540 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12541 break;
12542 case VMX_EXIT_MOV_DRX:
12543 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12544 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12545 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12546 SET_BOTH(DRX_READ);
12547 else
12548 SET_BOTH(DRX_WRITE);
12549 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12550 break;
12551 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12552 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12553 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12554 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12555 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12556 case VMX_EXIT_GDTR_IDTR_ACCESS:
12557 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12558 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12559 {
12560 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12561 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12562 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12563 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12564 }
12565 break;
12566
12567 case VMX_EXIT_LDTR_TR_ACCESS:
12568 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12569 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12570 {
12571 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12572 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12573 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12574 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12575 }
12576 break;
12577
12578 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12579 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12580 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12581 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12582 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12583 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12584 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12585 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12586 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12587 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12588 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12589
12590 /* Events that aren't relevant at this point. */
12591 case VMX_EXIT_EXT_INT:
12592 case VMX_EXIT_INT_WINDOW:
12593 case VMX_EXIT_NMI_WINDOW:
12594 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12595 case VMX_EXIT_PREEMPT_TIMER:
12596 case VMX_EXIT_IO_INSTR:
12597 break;
12598
12599 /* Errors and unexpected events. */
12600 case VMX_EXIT_INIT_SIGNAL:
12601 case VMX_EXIT_SIPI:
12602 case VMX_EXIT_IO_SMI:
12603 case VMX_EXIT_SMI:
12604 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12605 case VMX_EXIT_ERR_MSR_LOAD:
12606 case VMX_EXIT_ERR_MACHINE_CHECK:
12607 case VMX_EXIT_PML_FULL:
12608 case VMX_EXIT_VIRTUALIZED_EOI:
12609 break;
12610
12611 default:
12612 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12613 break;
12614 }
12615#undef SET_BOTH
12616#undef SET_EXIT
12617
12618 /*
12619 * Dtrace tracepoints go first. We do them here at once so we don't
12620 * have to copy the guest state saving and stuff a few dozen times.
12621 * Down side is that we've got to repeat the switch, though this time
12622 * we use enmEvent since the probes are a subset of what DBGF does.
12623 */
12624 if (fDtrace1 || fDtrace2)
12625 {
12626 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12627 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12628 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12629 switch (enmEvent1)
12630 {
12631 /** @todo consider which extra parameters would be helpful for each probe. */
12632 case DBGFEVENT_END: break;
12633 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12634 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12635 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12636 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12637 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12638 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12639 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12640 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12641 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12642 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12643 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12644 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12645 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12646 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12647 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12648 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12649 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12650 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12651 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12652 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12653 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12654 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12655 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12656 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12657 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12658 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12659 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12660 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12661 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12662 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12663 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12664 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12665 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12666 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12667 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12668 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12669 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12670 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12671 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12672 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12673 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12674 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12675 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12676 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12677 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12678 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12679 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12680 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12681 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12682 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12683 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12684 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12685 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12686 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12687 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12688 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12689 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12690 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12691 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12692 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12693 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12694 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12695 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12696 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12697 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12698 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12699 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12700 }
12701 switch (enmEvent2)
12702 {
12703 /** @todo consider which extra parameters would be helpful for each probe. */
12704 case DBGFEVENT_END: break;
12705 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12706 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12707 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12708 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12709 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12710 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12711 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12712 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12713 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12714 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12715 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12716 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12717 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12718 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12719 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12720 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12721 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12722 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12723 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12724 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12725 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12726 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12727 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12728 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12729 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12730 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12731 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12732 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12733 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12734 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12735 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12736 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12737 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12738 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12739 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12740 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12741 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12742 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12743 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12744 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12745 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12746 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12747 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12748 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12749 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12750 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12751 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12752 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12753 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12754 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12755 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12756 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12757 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12758 }
12759 }
12760
12761 /*
12762 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12763 * the DBGF call will do a full check).
12764 *
12765 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12766 * Note! If we have to events, we prioritize the first, i.e. the instruction
12767 * one, in order to avoid event nesting.
12768 */
12769 PVM pVM = pVCpu->CTX_SUFF(pVM);
12770 if ( enmEvent1 != DBGFEVENT_END
12771 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12772 {
12773 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12774 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12775 if (rcStrict != VINF_SUCCESS)
12776 return rcStrict;
12777 }
12778 else if ( enmEvent2 != DBGFEVENT_END
12779 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12780 {
12781 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12782 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12783 if (rcStrict != VINF_SUCCESS)
12784 return rcStrict;
12785 }
12786
12787 return VINF_SUCCESS;
12788}
12789
12790
12791/**
12792 * Single-stepping VM-exit filtering.
12793 *
12794 * This is preprocessing the VM-exits and deciding whether we've gotten far
12795 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12796 * handling is performed.
12797 *
12798 * @returns Strict VBox status code (i.e. informational status codes too).
12799 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12800 * @param pVmxTransient The VMX-transient structure.
12801 * @param pDbgState The debug state.
12802 */
12803DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12804{
12805 /*
12806 * Expensive (saves context) generic dtrace VM-exit probe.
12807 */
12808 uint32_t const uExitReason = pVmxTransient->uExitReason;
12809 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12810 { /* more likely */ }
12811 else
12812 {
12813 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12814 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12815 AssertRC(rc);
12816 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12817 }
12818
12819 /*
12820 * Check for host NMI, just to get that out of the way.
12821 */
12822 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12823 { /* normally likely */ }
12824 else
12825 {
12826 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12827 AssertRCReturn(rc2, rc2);
12828 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12829 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12830 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12831 }
12832
12833 /*
12834 * Check for single stepping event if we're stepping.
12835 */
12836 if (pVCpu->hm.s.fSingleInstruction)
12837 {
12838 switch (uExitReason)
12839 {
12840 case VMX_EXIT_MTF:
12841 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12842
12843 /* Various events: */
12844 case VMX_EXIT_XCPT_OR_NMI:
12845 case VMX_EXIT_EXT_INT:
12846 case VMX_EXIT_TRIPLE_FAULT:
12847 case VMX_EXIT_INT_WINDOW:
12848 case VMX_EXIT_NMI_WINDOW:
12849 case VMX_EXIT_TASK_SWITCH:
12850 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12851 case VMX_EXIT_APIC_ACCESS:
12852 case VMX_EXIT_EPT_VIOLATION:
12853 case VMX_EXIT_EPT_MISCONFIG:
12854 case VMX_EXIT_PREEMPT_TIMER:
12855
12856 /* Instruction specific VM-exits: */
12857 case VMX_EXIT_CPUID:
12858 case VMX_EXIT_GETSEC:
12859 case VMX_EXIT_HLT:
12860 case VMX_EXIT_INVD:
12861 case VMX_EXIT_INVLPG:
12862 case VMX_EXIT_RDPMC:
12863 case VMX_EXIT_RDTSC:
12864 case VMX_EXIT_RSM:
12865 case VMX_EXIT_VMCALL:
12866 case VMX_EXIT_VMCLEAR:
12867 case VMX_EXIT_VMLAUNCH:
12868 case VMX_EXIT_VMPTRLD:
12869 case VMX_EXIT_VMPTRST:
12870 case VMX_EXIT_VMREAD:
12871 case VMX_EXIT_VMRESUME:
12872 case VMX_EXIT_VMWRITE:
12873 case VMX_EXIT_VMXOFF:
12874 case VMX_EXIT_VMXON:
12875 case VMX_EXIT_MOV_CRX:
12876 case VMX_EXIT_MOV_DRX:
12877 case VMX_EXIT_IO_INSTR:
12878 case VMX_EXIT_RDMSR:
12879 case VMX_EXIT_WRMSR:
12880 case VMX_EXIT_MWAIT:
12881 case VMX_EXIT_MONITOR:
12882 case VMX_EXIT_PAUSE:
12883 case VMX_EXIT_GDTR_IDTR_ACCESS:
12884 case VMX_EXIT_LDTR_TR_ACCESS:
12885 case VMX_EXIT_INVEPT:
12886 case VMX_EXIT_RDTSCP:
12887 case VMX_EXIT_INVVPID:
12888 case VMX_EXIT_WBINVD:
12889 case VMX_EXIT_XSETBV:
12890 case VMX_EXIT_RDRAND:
12891 case VMX_EXIT_INVPCID:
12892 case VMX_EXIT_VMFUNC:
12893 case VMX_EXIT_RDSEED:
12894 case VMX_EXIT_XSAVES:
12895 case VMX_EXIT_XRSTORS:
12896 {
12897 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12898 AssertRCReturn(rc, rc);
12899 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12900 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12901 return VINF_EM_DBG_STEPPED;
12902 break;
12903 }
12904
12905 /* Errors and unexpected events: */
12906 case VMX_EXIT_INIT_SIGNAL:
12907 case VMX_EXIT_SIPI:
12908 case VMX_EXIT_IO_SMI:
12909 case VMX_EXIT_SMI:
12910 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12911 case VMX_EXIT_ERR_MSR_LOAD:
12912 case VMX_EXIT_ERR_MACHINE_CHECK:
12913 case VMX_EXIT_PML_FULL:
12914 case VMX_EXIT_VIRTUALIZED_EOI:
12915 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12916 break;
12917
12918 default:
12919 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12920 break;
12921 }
12922 }
12923
12924 /*
12925 * Check for debugger event breakpoints and dtrace probes.
12926 */
12927 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12928 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12929 {
12930 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12931 if (rcStrict != VINF_SUCCESS)
12932 return rcStrict;
12933 }
12934
12935 /*
12936 * Normal processing.
12937 */
12938#ifdef HMVMX_USE_FUNCTION_TABLE
12939 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12940#else
12941 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12942#endif
12943}
12944
12945
12946/**
12947 * Single steps guest code using hardware-assisted VMX.
12948 *
12949 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12950 * but single-stepping through the hypervisor debugger.
12951 *
12952 * @returns Strict VBox status code (i.e. informational status codes too).
12953 * @param pVCpu The cross context virtual CPU structure.
12954 * @param pcLoops Pointer to the number of executed loops.
12955 *
12956 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12957 */
12958static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12959{
12960 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12961 Assert(pcLoops);
12962 Assert(*pcLoops <= cMaxResumeLoops);
12963
12964 VMXTRANSIENT VmxTransient;
12965 RT_ZERO(VmxTransient);
12966 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12967
12968 /* Set HMCPU indicators. */
12969 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12970 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12971 pVCpu->hm.s.fDebugWantRdTscExit = false;
12972 pVCpu->hm.s.fUsingDebugLoop = true;
12973
12974 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12975 VMXRUNDBGSTATE DbgState;
12976 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12977 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12978
12979 /*
12980 * The loop.
12981 */
12982 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12983 for (;;)
12984 {
12985 Assert(!HMR0SuspendPending());
12986 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12987 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12988 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12989
12990 /* Set up VM-execution controls the next two can respond to. */
12991 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12992
12993 /*
12994 * Preparatory work for running guest code, this may force us to
12995 * return to ring-3.
12996 *
12997 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12998 */
12999 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
13000 if (rcStrict != VINF_SUCCESS)
13001 break;
13002
13003 /* Interrupts are disabled at this point! */
13004 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
13005
13006 /* Override any obnoxious code in the above two calls. */
13007 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
13008
13009 /*
13010 * Finally execute the guest.
13011 */
13012 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
13013
13014 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
13015 /* Interrupts are re-enabled at this point! */
13016
13017 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
13018 if (RT_SUCCESS(rcRun))
13019 { /* very likely */ }
13020 else
13021 {
13022 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
13023 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
13024 return rcRun;
13025 }
13026
13027 /* Profile the VM-exit. */
13028 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
13029 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
13030 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
13031 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
13032 HMVMX_START_EXIT_DISPATCH_PROF();
13033
13034 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
13035
13036 /*
13037 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
13038 */
13039 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
13040 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
13041 if (rcStrict != VINF_SUCCESS)
13042 break;
13043 if (++(*pcLoops) > cMaxResumeLoops)
13044 {
13045 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
13046 rcStrict = VINF_EM_RAW_INTERRUPT;
13047 break;
13048 }
13049
13050 /*
13051 * Stepping: Did the RIP change, if so, consider it a single step.
13052 * Otherwise, make sure one of the TFs gets set.
13053 */
13054 if (fStepping)
13055 {
13056 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13057 AssertRC(rc);
13058 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
13059 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
13060 {
13061 rcStrict = VINF_EM_DBG_STEPPED;
13062 break;
13063 }
13064 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
13065 }
13066
13067 /*
13068 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
13069 */
13070 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
13071 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
13072 }
13073
13074 /*
13075 * Clear the X86_EFL_TF if necessary.
13076 */
13077 if (pVCpu->hm.s.fClearTrapFlag)
13078 {
13079 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
13080 AssertRC(rc);
13081 pVCpu->hm.s.fClearTrapFlag = false;
13082 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
13083 }
13084 /** @todo there seems to be issues with the resume flag when the monitor trap
13085 * flag is pending without being used. Seen early in bios init when
13086 * accessing APIC page in protected mode. */
13087
13088 /*
13089 * Restore VM-exit control settings as we may not re-enter this function the
13090 * next time around.
13091 */
13092 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
13093
13094 /* Restore HMCPU indicators. */
13095 pVCpu->hm.s.fUsingDebugLoop = false;
13096 pVCpu->hm.s.fDebugWantRdTscExit = false;
13097 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
13098
13099 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
13100 return rcStrict;
13101}
13102
13103
13104/** @} */
13105
13106
13107/**
13108 * Checks if any expensive dtrace probes are enabled and we should go to the
13109 * debug loop.
13110 *
13111 * @returns true if we should use debug loop, false if not.
13112 */
13113static bool hmR0VmxAnyExpensiveProbesEnabled(void)
13114{
13115 /* It's probably faster to OR the raw 32-bit counter variables together.
13116 Since the variables are in an array and the probes are next to one
13117 another (more or less), we have good locality. So, better read
13118 eight-nine cache lines ever time and only have one conditional, than
13119 128+ conditionals, right? */
13120 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
13121 | VBOXVMM_XCPT_DE_ENABLED_RAW()
13122 | VBOXVMM_XCPT_DB_ENABLED_RAW()
13123 | VBOXVMM_XCPT_BP_ENABLED_RAW()
13124 | VBOXVMM_XCPT_OF_ENABLED_RAW()
13125 | VBOXVMM_XCPT_BR_ENABLED_RAW()
13126 | VBOXVMM_XCPT_UD_ENABLED_RAW()
13127 | VBOXVMM_XCPT_NM_ENABLED_RAW()
13128 | VBOXVMM_XCPT_DF_ENABLED_RAW()
13129 | VBOXVMM_XCPT_TS_ENABLED_RAW()
13130 | VBOXVMM_XCPT_NP_ENABLED_RAW()
13131 | VBOXVMM_XCPT_SS_ENABLED_RAW()
13132 | VBOXVMM_XCPT_GP_ENABLED_RAW()
13133 | VBOXVMM_XCPT_PF_ENABLED_RAW()
13134 | VBOXVMM_XCPT_MF_ENABLED_RAW()
13135 | VBOXVMM_XCPT_AC_ENABLED_RAW()
13136 | VBOXVMM_XCPT_XF_ENABLED_RAW()
13137 | VBOXVMM_XCPT_VE_ENABLED_RAW()
13138 | VBOXVMM_XCPT_SX_ENABLED_RAW()
13139 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
13140 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
13141 ) != 0
13142 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
13143 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
13144 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
13145 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
13146 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
13147 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
13148 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
13149 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
13150 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
13151 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
13152 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
13153 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
13154 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
13155 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
13156 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
13157 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
13158 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
13159 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
13160 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
13161 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
13162 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
13163 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
13164 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
13165 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
13166 | VBOXVMM_INSTR_STR_ENABLED_RAW()
13167 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
13168 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
13169 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
13170 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
13171 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13172 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13173 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13174 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13175 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13176 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13177 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13178 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13179 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13180 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13181 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13182 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13183 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13184 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13185 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13186 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13187 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13188 ) != 0
13189 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13190 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13191 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13192 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13193 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13194 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13195 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13196 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13197 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13198 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13199 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13200 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13201 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13202 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13203 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13204 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13205 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13206 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13207 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13208 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13209 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13210 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13211 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13212 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13213 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13214 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13215 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13216 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13217 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13218 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13219 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13220 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13221 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13222 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13223 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13224 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13225 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13226 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13227 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13228 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13229 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13230 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13231 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13232 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13233 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13234 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13235 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13236 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13237 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13238 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13239 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13240 ) != 0;
13241}
13242
13243
13244/**
13245 * Runs the guest using hardware-assisted VMX.
13246 *
13247 * @returns Strict VBox status code (i.e. informational status codes too).
13248 * @param pVCpu The cross context virtual CPU structure.
13249 */
13250VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13251{
13252 AssertPtr(pVCpu);
13253 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13254 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13255 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13256 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13257
13258 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13259
13260 VBOXSTRICTRC rcStrict;
13261 uint32_t cLoops = 0;
13262 for (;;)
13263 {
13264#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13265 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13266#else
13267 bool const fInNestedGuestMode = false;
13268#endif
13269 if (!fInNestedGuestMode)
13270 {
13271 if ( !pVCpu->hm.s.fUseDebugLoop
13272 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13273 && !DBGFIsStepping(pVCpu)
13274 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13275 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13276 else
13277 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13278 }
13279#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13280 else
13281 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13282
13283 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13284 {
13285 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13286 continue;
13287 }
13288 if (rcStrict == VINF_VMX_VMEXIT)
13289 {
13290 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13291 continue;
13292 }
13293#endif
13294 break;
13295 }
13296
13297 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13298 switch (rcLoop)
13299 {
13300 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13301 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13302 }
13303
13304 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13305 if (RT_FAILURE(rc2))
13306 {
13307 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13308 rcStrict = rc2;
13309 }
13310 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13311 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13312 return rcStrict;
13313}
13314
13315
13316#ifndef HMVMX_USE_FUNCTION_TABLE
13317/**
13318 * Handles a guest VM-exit from hardware-assisted VMX execution.
13319 *
13320 * @returns Strict VBox status code (i.e. informational status codes too).
13321 * @param pVCpu The cross context virtual CPU structure.
13322 * @param pVmxTransient The VMX-transient structure.
13323 */
13324DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13325{
13326#ifdef DEBUG_ramshankar
13327#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13328 do { \
13329 if (a_fSave != 0) \
13330 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13331 VBOXSTRICTRC rcStrict = a_CallExpr; \
13332 if (a_fSave != 0) \
13333 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13334 return rcStrict; \
13335 } while (0)
13336#else
13337# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13338#endif
13339 uint32_t const uExitReason = pVmxTransient->uExitReason;
13340 switch (uExitReason)
13341 {
13342 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13343 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13344 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13345 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13346 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13347 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13348 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13349 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13350 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13351 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13352 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13353 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13354 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13355 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13356 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13357 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13358 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13359 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13360 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13361 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13362 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13363 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13364 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13365 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13366 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13367 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13368 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13369 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13370 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13371 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13372#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13373 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13374 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13375 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13376 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13377 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13378 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13379 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13380 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13381 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13382 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13383 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13384#else
13385 case VMX_EXIT_VMCLEAR:
13386 case VMX_EXIT_VMLAUNCH:
13387 case VMX_EXIT_VMPTRLD:
13388 case VMX_EXIT_VMPTRST:
13389 case VMX_EXIT_VMREAD:
13390 case VMX_EXIT_VMRESUME:
13391 case VMX_EXIT_VMWRITE:
13392 case VMX_EXIT_VMXOFF:
13393 case VMX_EXIT_VMXON:
13394 case VMX_EXIT_INVVPID:
13395 case VMX_EXIT_INVEPT:
13396 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13397#endif
13398
13399 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13400 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13401 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13402
13403 case VMX_EXIT_INIT_SIGNAL:
13404 case VMX_EXIT_SIPI:
13405 case VMX_EXIT_IO_SMI:
13406 case VMX_EXIT_SMI:
13407 case VMX_EXIT_ERR_MSR_LOAD:
13408 case VMX_EXIT_ERR_MACHINE_CHECK:
13409 case VMX_EXIT_PML_FULL:
13410 case VMX_EXIT_VIRTUALIZED_EOI:
13411 case VMX_EXIT_GDTR_IDTR_ACCESS:
13412 case VMX_EXIT_LDTR_TR_ACCESS:
13413 case VMX_EXIT_APIC_WRITE:
13414 case VMX_EXIT_RDRAND:
13415 case VMX_EXIT_RSM:
13416 case VMX_EXIT_VMFUNC:
13417 case VMX_EXIT_ENCLS:
13418 case VMX_EXIT_RDSEED:
13419 case VMX_EXIT_XSAVES:
13420 case VMX_EXIT_XRSTORS:
13421 case VMX_EXIT_UMWAIT:
13422 case VMX_EXIT_TPAUSE:
13423 default:
13424 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13425 }
13426#undef VMEXIT_CALL_RET
13427}
13428#endif /* !HMVMX_USE_FUNCTION_TABLE */
13429
13430
13431#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13432/**
13433 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13434 *
13435 * @returns Strict VBox status code (i.e. informational status codes too).
13436 * @param pVCpu The cross context virtual CPU structure.
13437 * @param pVmxTransient The VMX-transient structure.
13438 */
13439DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13440{
13441 uint32_t const uExitReason = pVmxTransient->uExitReason;
13442 switch (uExitReason)
13443 {
13444 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13445 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13446 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13447 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13448 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13449
13450 /*
13451 * We shouldn't direct host physical interrupts to the nested-guest.
13452 */
13453 case VMX_EXIT_EXT_INT:
13454 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13455
13456 /*
13457 * Instructions that cause VM-exits unconditionally or the condition is
13458 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13459 * happens, it's guaranteed to be a nested-guest VM-exit).
13460 *
13461 * - Provides VM-exit instruction length ONLY.
13462 */
13463 case VMX_EXIT_CPUID: /* Unconditional. */
13464 case VMX_EXIT_VMCALL:
13465 case VMX_EXIT_GETSEC:
13466 case VMX_EXIT_INVD:
13467 case VMX_EXIT_XSETBV:
13468 case VMX_EXIT_VMLAUNCH:
13469 case VMX_EXIT_VMRESUME:
13470 case VMX_EXIT_VMXOFF:
13471 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13472 case VMX_EXIT_VMFUNC:
13473 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13474
13475 /*
13476 * Instructions that cause VM-exits unconditionally or the condition is
13477 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13478 * happens, it's guaranteed to be a nested-guest VM-exit).
13479 *
13480 * - Provides VM-exit instruction length.
13481 * - Provides VM-exit information.
13482 * - Optionally provides Exit qualification.
13483 *
13484 * Since Exit qualification is 0 for all VM-exits where it is not
13485 * applicable, reading and passing it to the guest should produce
13486 * defined behavior.
13487 *
13488 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13489 */
13490 case VMX_EXIT_INVEPT: /* Unconditional. */
13491 case VMX_EXIT_INVVPID:
13492 case VMX_EXIT_VMCLEAR:
13493 case VMX_EXIT_VMPTRLD:
13494 case VMX_EXIT_VMPTRST:
13495 case VMX_EXIT_VMXON:
13496 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13497 case VMX_EXIT_LDTR_TR_ACCESS:
13498 case VMX_EXIT_RDRAND:
13499 case VMX_EXIT_RDSEED:
13500 case VMX_EXIT_XSAVES:
13501 case VMX_EXIT_XRSTORS:
13502 case VMX_EXIT_UMWAIT:
13503 case VMX_EXIT_TPAUSE:
13504 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13505
13506 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13507 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13508 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13509 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13510 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13511 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13512 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13513 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13514 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13515 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13516 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13517 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13518 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13519 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13520 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13521 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13522 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13523 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13524 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13525
13526 case VMX_EXIT_PREEMPT_TIMER:
13527 {
13528 /** @todo NSTVMX: Preempt timer. */
13529 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13530 }
13531
13532 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13533 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13534
13535 case VMX_EXIT_VMREAD:
13536 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13537
13538 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13539 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13540
13541 case VMX_EXIT_INIT_SIGNAL:
13542 case VMX_EXIT_SIPI:
13543 case VMX_EXIT_IO_SMI:
13544 case VMX_EXIT_SMI:
13545 case VMX_EXIT_ERR_MSR_LOAD:
13546 case VMX_EXIT_ERR_MACHINE_CHECK:
13547 case VMX_EXIT_PML_FULL:
13548 case VMX_EXIT_RSM:
13549 default:
13550 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13551 }
13552}
13553#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13554
13555
13556/** @name VM-exit helpers.
13557 * @{
13558 */
13559/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13560/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13561/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13562
13563/** Macro for VM-exits called unexpectedly. */
13564#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13565 do { \
13566 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13567 return VERR_VMX_UNEXPECTED_EXIT; \
13568 } while (0)
13569
13570#ifdef VBOX_STRICT
13571/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13572# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13573 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13574
13575# define HMVMX_ASSERT_PREEMPT_CPUID() \
13576 do { \
13577 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13578 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13579 } while (0)
13580
13581# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13582 do { \
13583 AssertPtr((a_pVCpu)); \
13584 AssertPtr((a_pVmxTransient)); \
13585 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13586 Assert((a_pVmxTransient)->pVmcsInfo); \
13587 Assert(ASMIntAreEnabled()); \
13588 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13589 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13590 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13591 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13592 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13593 HMVMX_ASSERT_PREEMPT_CPUID(); \
13594 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13595 } while (0)
13596
13597# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13598 do { \
13599 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13600 Assert((a_pVmxTransient)->fIsNestedGuest); \
13601 } while (0)
13602
13603# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13604 do { \
13605 Log4Func(("\n")); \
13606 } while (0)
13607#else
13608# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13609 do { \
13610 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13611 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13612 } while (0)
13613
13614# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13615 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13616
13617# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13618#endif
13619
13620#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13621/** Macro that does the necessary privilege checks and intercepted VM-exits for
13622 * guests that attempted to execute a VMX instruction. */
13623# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13624 do \
13625 { \
13626 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13627 if (rcStrictTmp == VINF_SUCCESS) \
13628 { /* likely */ } \
13629 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13630 { \
13631 Assert((a_pVCpu)->hm.s.Event.fPending); \
13632 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13633 return VINF_SUCCESS; \
13634 } \
13635 else \
13636 { \
13637 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13638 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13639 } \
13640 } while (0)
13641
13642/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13643# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13644 do \
13645 { \
13646 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13647 (a_pGCPtrEffAddr)); \
13648 if (rcStrictTmp == VINF_SUCCESS) \
13649 { /* likely */ } \
13650 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13651 { \
13652 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13653 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13654 NOREF(uXcptTmp); \
13655 return VINF_SUCCESS; \
13656 } \
13657 else \
13658 { \
13659 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13660 return rcStrictTmp; \
13661 } \
13662 } while (0)
13663#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13664
13665
13666/**
13667 * Advances the guest RIP by the specified number of bytes.
13668 *
13669 * @param pVCpu The cross context virtual CPU structure.
13670 * @param cbInstr Number of bytes to advance the RIP by.
13671 *
13672 * @remarks No-long-jump zone!!!
13673 */
13674DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13675{
13676 /* Advance the RIP. */
13677 pVCpu->cpum.GstCtx.rip += cbInstr;
13678 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13679
13680 /* Update interrupt inhibition. */
13681 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13682 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13683 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13684}
13685
13686
13687/**
13688 * Advances the guest RIP after reading it from the VMCS.
13689 *
13690 * @returns VBox status code, no informational status codes.
13691 * @param pVCpu The cross context virtual CPU structure.
13692 * @param pVmxTransient The VMX-transient structure.
13693 *
13694 * @remarks No-long-jump zone!!!
13695 */
13696static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13697{
13698 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13699 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13700 AssertRCReturn(rc, rc);
13701
13702 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13703 return VINF_SUCCESS;
13704}
13705
13706
13707/**
13708 * Handle a condition that occurred while delivering an event through the guest or
13709 * nested-guest IDT.
13710 *
13711 * @returns Strict VBox status code (i.e. informational status codes too).
13712 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13713 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13714 * to continue execution of the guest which will delivery the \#DF.
13715 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13716 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13717 *
13718 * @param pVCpu The cross context virtual CPU structure.
13719 * @param pVmxTransient The VMX-transient structure.
13720 *
13721 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13722 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13723 * is due to an EPT violation, PML full or SPP-related event.
13724 *
13725 * @remarks No-long-jump zone!!!
13726 */
13727static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13728{
13729 Assert(!pVCpu->hm.s.Event.fPending);
13730 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13731 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13732 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13733 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13734 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13735
13736 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13737 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13738 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13739 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13740 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13741 {
13742 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13743 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13744
13745 /*
13746 * If the event was a software interrupt (generated with INT n) or a software exception
13747 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13748 * can handle the VM-exit and continue guest execution which will re-execute the
13749 * instruction rather than re-injecting the exception, as that can cause premature
13750 * trips to ring-3 before injection and involve TRPM which currently has no way of
13751 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13752 * the problem).
13753 */
13754 IEMXCPTRAISE enmRaise;
13755 IEMXCPTRAISEINFO fRaiseInfo;
13756 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13757 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13758 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13759 {
13760 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13761 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13762 }
13763 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13764 {
13765 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13766 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13767 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13768
13769 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13770 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13771
13772 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13773
13774 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13775 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13776 {
13777 pVmxTransient->fVectoringPF = true;
13778 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13779 }
13780 }
13781 else
13782 {
13783 /*
13784 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13785 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13786 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13787 */
13788 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13789 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13790 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13791 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13792 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13793 }
13794
13795 /*
13796 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13797 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13798 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13799 * subsequent VM-entry would fail, see @bugref{7445}.
13800 *
13801 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13802 */
13803 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13804 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13805 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13806 && CPUMIsGuestNmiBlocking(pVCpu))
13807 {
13808 CPUMSetGuestNmiBlocking(pVCpu, false);
13809 }
13810
13811 switch (enmRaise)
13812 {
13813 case IEMXCPTRAISE_CURRENT_XCPT:
13814 {
13815 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13816 Assert(rcStrict == VINF_SUCCESS);
13817 break;
13818 }
13819
13820 case IEMXCPTRAISE_PREV_EVENT:
13821 {
13822 uint32_t u32ErrCode;
13823 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13824 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13825 else
13826 u32ErrCode = 0;
13827
13828 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13829 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13830 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13831 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13832
13833 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13834 pVCpu->hm.s.Event.u32ErrCode));
13835 Assert(rcStrict == VINF_SUCCESS);
13836 break;
13837 }
13838
13839 case IEMXCPTRAISE_REEXEC_INSTR:
13840 Assert(rcStrict == VINF_SUCCESS);
13841 break;
13842
13843 case IEMXCPTRAISE_DOUBLE_FAULT:
13844 {
13845 /*
13846 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13847 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13848 */
13849 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13850 {
13851 pVmxTransient->fVectoringDoublePF = true;
13852 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13853 pVCpu->cpum.GstCtx.cr2));
13854 rcStrict = VINF_SUCCESS;
13855 }
13856 else
13857 {
13858 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13859 hmR0VmxSetPendingXcptDF(pVCpu);
13860 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13861 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13862 rcStrict = VINF_HM_DOUBLE_FAULT;
13863 }
13864 break;
13865 }
13866
13867 case IEMXCPTRAISE_TRIPLE_FAULT:
13868 {
13869 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13870 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13871 rcStrict = VINF_EM_RESET;
13872 break;
13873 }
13874
13875 case IEMXCPTRAISE_CPU_HANG:
13876 {
13877 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13878 rcStrict = VERR_EM_GUEST_CPU_HANG;
13879 break;
13880 }
13881
13882 default:
13883 {
13884 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13885 rcStrict = VERR_VMX_IPE_2;
13886 break;
13887 }
13888 }
13889 }
13890 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13891 && !CPUMIsGuestNmiBlocking(pVCpu))
13892 {
13893 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13894 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13895 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13896 {
13897 /*
13898 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13899 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13900 * that NMIs remain blocked until the IRET execution is completed.
13901 *
13902 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13903 */
13904 CPUMSetGuestNmiBlocking(pVCpu, true);
13905 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13906 }
13907 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13908 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13909 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13910 {
13911 /*
13912 * Execution of IRET caused an EPT violation, page-modification log-full event or
13913 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13914 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13915 * that NMIs remain blocked until the IRET execution is completed.
13916 *
13917 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13918 */
13919 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13920 {
13921 CPUMSetGuestNmiBlocking(pVCpu, true);
13922 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13923 }
13924 }
13925 }
13926
13927 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13928 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13929 return rcStrict;
13930}
13931
13932
13933#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13934/**
13935 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13936 * guest attempting to execute a VMX instruction.
13937 *
13938 * @returns Strict VBox status code (i.e. informational status codes too).
13939 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13940 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13941 *
13942 * @param pVCpu The cross context virtual CPU structure.
13943 * @param uExitReason The VM-exit reason.
13944 *
13945 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13946 * @remarks No-long-jump zone!!!
13947 */
13948static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13949{
13950 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13951 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13952
13953 /*
13954 * The physical CPU would have already checked the CPU mode/code segment.
13955 * We shall just assert here for paranoia.
13956 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13957 */
13958 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13959 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13960 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13961
13962 if (uExitReason == VMX_EXIT_VMXON)
13963 {
13964 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13965
13966 /*
13967 * We check CR4.VMXE because it is required to be always set while in VMX operation
13968 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13969 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13970 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13971 */
13972 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13973 {
13974 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13975 hmR0VmxSetPendingXcptUD(pVCpu);
13976 return VINF_HM_PENDING_XCPT;
13977 }
13978 }
13979 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13980 {
13981 /*
13982 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13983 * (other than VMXON), we need to raise a #UD.
13984 */
13985 Log4Func(("Not in VMX root mode -> #UD\n"));
13986 hmR0VmxSetPendingXcptUD(pVCpu);
13987 return VINF_HM_PENDING_XCPT;
13988 }
13989
13990 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13991 return VINF_SUCCESS;
13992}
13993
13994/**
13995 * Decodes the memory operand of an instruction that caused a VM-exit.
13996 *
13997 * The Exit qualification field provides the displacement field for memory
13998 * operand instructions, if any.
13999 *
14000 * @returns Strict VBox status code (i.e. informational status codes too).
14001 * @retval VINF_SUCCESS if the operand was successfully decoded.
14002 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
14003 * operand.
14004 * @param pVCpu The cross context virtual CPU structure.
14005 * @param uExitInstrInfo The VM-exit instruction information field.
14006 * @param enmMemAccess The memory operand's access type (read or write).
14007 * @param GCPtrDisp The instruction displacement field, if any. For
14008 * RIP-relative addressing pass RIP + displacement here.
14009 * @param pGCPtrMem Where to store the effective destination memory address.
14010 *
14011 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
14012 * virtual-8086 mode hence skips those checks while verifying if the
14013 * segment is valid.
14014 */
14015static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
14016 PRTGCPTR pGCPtrMem)
14017{
14018 Assert(pGCPtrMem);
14019 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
14020 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
14021 | CPUMCTX_EXTRN_CR0);
14022
14023 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
14024 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
14025 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
14026
14027 VMXEXITINSTRINFO ExitInstrInfo;
14028 ExitInstrInfo.u = uExitInstrInfo;
14029 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
14030 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
14031 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
14032 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
14033 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
14034 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
14035 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
14036 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
14037 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
14038
14039 /*
14040 * Validate instruction information.
14041 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
14042 */
14043 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
14044 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
14045 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
14046 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
14047 AssertLogRelMsgReturn(fIsMemOperand,
14048 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
14049
14050 /*
14051 * Compute the complete effective address.
14052 *
14053 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
14054 * See AMD spec. 4.5.2 "Segment Registers".
14055 */
14056 RTGCPTR GCPtrMem = GCPtrDisp;
14057 if (fBaseRegValid)
14058 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
14059 if (fIdxRegValid)
14060 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
14061
14062 RTGCPTR const GCPtrOff = GCPtrMem;
14063 if ( !fIsLongMode
14064 || iSegReg >= X86_SREG_FS)
14065 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
14066 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
14067
14068 /*
14069 * Validate effective address.
14070 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
14071 */
14072 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
14073 Assert(cbAccess > 0);
14074 if (fIsLongMode)
14075 {
14076 if (X86_IS_CANONICAL(GCPtrMem))
14077 {
14078 *pGCPtrMem = GCPtrMem;
14079 return VINF_SUCCESS;
14080 }
14081
14082 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
14083 * "Data Limit Checks in 64-bit Mode". */
14084 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
14085 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14086 return VINF_HM_PENDING_XCPT;
14087 }
14088
14089 /*
14090 * This is a watered down version of iemMemApplySegment().
14091 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
14092 * and segment CPL/DPL checks are skipped.
14093 */
14094 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
14095 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
14096 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
14097
14098 /* Check if the segment is present and usable. */
14099 if ( pSel->Attr.n.u1Present
14100 && !pSel->Attr.n.u1Unusable)
14101 {
14102 Assert(pSel->Attr.n.u1DescType);
14103 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
14104 {
14105 /* Check permissions for the data segment. */
14106 if ( enmMemAccess == VMXMEMACCESS_WRITE
14107 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
14108 {
14109 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14110 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
14111 return VINF_HM_PENDING_XCPT;
14112 }
14113
14114 /* Check limits if it's a normal data segment. */
14115 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
14116 {
14117 if ( GCPtrFirst32 > pSel->u32Limit
14118 || GCPtrLast32 > pSel->u32Limit)
14119 {
14120 Log4Func(("Data segment limit exceeded. "
14121 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14122 GCPtrLast32, pSel->u32Limit));
14123 if (iSegReg == X86_SREG_SS)
14124 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14125 else
14126 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14127 return VINF_HM_PENDING_XCPT;
14128 }
14129 }
14130 else
14131 {
14132 /* Check limits if it's an expand-down data segment.
14133 Note! The upper boundary is defined by the B bit, not the G bit! */
14134 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
14135 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
14136 {
14137 Log4Func(("Expand-down data segment limit exceeded. "
14138 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14139 GCPtrLast32, pSel->u32Limit));
14140 if (iSegReg == X86_SREG_SS)
14141 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14142 else
14143 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14144 return VINF_HM_PENDING_XCPT;
14145 }
14146 }
14147 }
14148 else
14149 {
14150 /* Check permissions for the code segment. */
14151 if ( enmMemAccess == VMXMEMACCESS_WRITE
14152 || ( enmMemAccess == VMXMEMACCESS_READ
14153 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
14154 {
14155 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
14156 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
14157 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14158 return VINF_HM_PENDING_XCPT;
14159 }
14160
14161 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
14162 if ( GCPtrFirst32 > pSel->u32Limit
14163 || GCPtrLast32 > pSel->u32Limit)
14164 {
14165 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
14166 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
14167 if (iSegReg == X86_SREG_SS)
14168 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14169 else
14170 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14171 return VINF_HM_PENDING_XCPT;
14172 }
14173 }
14174 }
14175 else
14176 {
14177 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14178 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14179 return VINF_HM_PENDING_XCPT;
14180 }
14181
14182 *pGCPtrMem = GCPtrMem;
14183 return VINF_SUCCESS;
14184}
14185#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
14186
14187
14188/**
14189 * VM-exit helper for LMSW.
14190 */
14191static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
14192{
14193 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14194 AssertRCReturn(rc, rc);
14195
14196 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14197 AssertMsg( rcStrict == VINF_SUCCESS
14198 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14199
14200 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14201 if (rcStrict == VINF_IEM_RAISED_XCPT)
14202 {
14203 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14204 rcStrict = VINF_SUCCESS;
14205 }
14206
14207 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14208 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14209 return rcStrict;
14210}
14211
14212
14213/**
14214 * VM-exit helper for CLTS.
14215 */
14216static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14217{
14218 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14219 AssertRCReturn(rc, rc);
14220
14221 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14222 AssertMsg( rcStrict == VINF_SUCCESS
14223 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14224
14225 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14226 if (rcStrict == VINF_IEM_RAISED_XCPT)
14227 {
14228 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14229 rcStrict = VINF_SUCCESS;
14230 }
14231
14232 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14233 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14234 return rcStrict;
14235}
14236
14237
14238/**
14239 * VM-exit helper for MOV from CRx (CRx read).
14240 */
14241static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14242{
14243 Assert(iCrReg < 16);
14244 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14245
14246 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14247 AssertRCReturn(rc, rc);
14248
14249 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14250 AssertMsg( rcStrict == VINF_SUCCESS
14251 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14252
14253 if (iGReg == X86_GREG_xSP)
14254 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14255 else
14256 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14257#ifdef VBOX_WITH_STATISTICS
14258 switch (iCrReg)
14259 {
14260 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14261 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14262 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14263 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14264 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14265 }
14266#endif
14267 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14268 return rcStrict;
14269}
14270
14271
14272/**
14273 * VM-exit helper for MOV to CRx (CRx write).
14274 */
14275static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14276{
14277 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14278 AssertRCReturn(rc, rc);
14279
14280 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14281 AssertMsg( rcStrict == VINF_SUCCESS
14282 || rcStrict == VINF_IEM_RAISED_XCPT
14283 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14284
14285 switch (iCrReg)
14286 {
14287 case 0:
14288 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14289 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14290 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14291 break;
14292
14293 case 2:
14294 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14295 /* Nothing to do here, CR2 it's not part of the VMCS. */
14296 break;
14297
14298 case 3:
14299 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14300 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14301 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14302 break;
14303
14304 case 4:
14305 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14306 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14307 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14308 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14309 break;
14310
14311 case 8:
14312 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14313 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14314 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14315 break;
14316
14317 default:
14318 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14319 break;
14320 }
14321
14322 if (rcStrict == VINF_IEM_RAISED_XCPT)
14323 {
14324 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14325 rcStrict = VINF_SUCCESS;
14326 }
14327 return rcStrict;
14328}
14329
14330
14331/**
14332 * VM-exit exception handler for \#PF (Page-fault exception).
14333 *
14334 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14335 */
14336static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14337{
14338 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14339 PVM pVM = pVCpu->CTX_SUFF(pVM);
14340 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14341 AssertRCReturn(rc, rc);
14342
14343 if (!pVM->hm.s.fNestedPaging)
14344 { /* likely */ }
14345 else
14346 {
14347#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14348 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14349#endif
14350 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14351 if (!pVmxTransient->fVectoringDoublePF)
14352 {
14353 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14354 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14355 }
14356 else
14357 {
14358 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14359 Assert(!pVmxTransient->fIsNestedGuest);
14360 hmR0VmxSetPendingXcptDF(pVCpu);
14361 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14362 }
14363 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14364 return rc;
14365 }
14366
14367 Assert(!pVmxTransient->fIsNestedGuest);
14368
14369 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14370 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14371 if (pVmxTransient->fVectoringPF)
14372 {
14373 Assert(pVCpu->hm.s.Event.fPending);
14374 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14375 }
14376
14377 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14378 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14379 AssertRCReturn(rc, rc);
14380
14381 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14382 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14383
14384 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14385 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14386
14387 Log4Func(("#PF: rc=%Rrc\n", rc));
14388 if (rc == VINF_SUCCESS)
14389 {
14390 /*
14391 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14392 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14393 */
14394 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14395 TRPMResetTrap(pVCpu);
14396 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14397 return rc;
14398 }
14399
14400 if (rc == VINF_EM_RAW_GUEST_TRAP)
14401 {
14402 if (!pVmxTransient->fVectoringDoublePF)
14403 {
14404 /* It's a guest page fault and needs to be reflected to the guest. */
14405 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14406 TRPMResetTrap(pVCpu);
14407 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14408 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14409 uGstErrorCode, pVmxTransient->uExitQual);
14410 }
14411 else
14412 {
14413 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14414 TRPMResetTrap(pVCpu);
14415 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14416 hmR0VmxSetPendingXcptDF(pVCpu);
14417 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14418 }
14419
14420 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14421 return VINF_SUCCESS;
14422 }
14423
14424 TRPMResetTrap(pVCpu);
14425 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14426 return rc;
14427}
14428
14429
14430/**
14431 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14432 *
14433 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14434 */
14435static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14436{
14437 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14438 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14439
14440 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14441 AssertRCReturn(rc, rc);
14442
14443 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14444 {
14445 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14446 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14447
14448 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14449 * provides VM-exit instruction length. If this causes problem later,
14450 * disassemble the instruction like it's done on AMD-V. */
14451 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14452 AssertRCReturn(rc2, rc2);
14453 return rc;
14454 }
14455
14456 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14457 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14458 return VINF_SUCCESS;
14459}
14460
14461
14462/**
14463 * VM-exit exception handler for \#BP (Breakpoint exception).
14464 *
14465 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14466 */
14467static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14468{
14469 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14470 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14471
14472 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14473 AssertRCReturn(rc, rc);
14474
14475 if (!pVmxTransient->fIsNestedGuest)
14476 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14477 else
14478 rc = VINF_EM_RAW_GUEST_TRAP;
14479 if (rc == VINF_EM_RAW_GUEST_TRAP)
14480 {
14481 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14482 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14483 }
14484
14485 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14486 return rc;
14487}
14488
14489
14490/**
14491 * VM-exit exception handler for \#AC (Alignment-check exception).
14492 *
14493 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14494 */
14495static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14496{
14497 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14498 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14499
14500 /* Re-inject it. We'll detect any nesting before getting here. */
14501 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14502 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14503 return VINF_SUCCESS;
14504}
14505
14506
14507/**
14508 * VM-exit exception handler for \#DB (Debug exception).
14509 *
14510 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14511 */
14512static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14513{
14514 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14515 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14516
14517 /*
14518 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14519 */
14520 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14521 AssertRCReturn(rc, rc);
14522
14523 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14524 uint64_t const uDR6 = X86_DR6_INIT_VAL
14525 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14526 | X86_DR6_BD | X86_DR6_BS));
14527
14528 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14529 if (!pVmxTransient->fIsNestedGuest)
14530 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14531 else
14532 rc = VINF_EM_RAW_GUEST_TRAP;
14533 Log6Func(("rc=%Rrc\n", rc));
14534 if (rc == VINF_EM_RAW_GUEST_TRAP)
14535 {
14536 /*
14537 * The exception was for the guest. Update DR6, DR7.GD and
14538 * IA32_DEBUGCTL.LBR before forwarding it.
14539 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14540 */
14541 VMMRZCallRing3Disable(pVCpu);
14542 HM_DISABLE_PREEMPT(pVCpu);
14543
14544 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14545 pCtx->dr[6] |= uDR6;
14546 if (CPUMIsGuestDebugStateActive(pVCpu))
14547 ASMSetDR6(pCtx->dr[6]);
14548
14549 HM_RESTORE_PREEMPT();
14550 VMMRZCallRing3Enable(pVCpu);
14551
14552 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14553 AssertRCReturn(rc, rc);
14554
14555 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14556 pCtx->dr[7] &= ~X86_DR7_GD;
14557
14558 /* Paranoia. */
14559 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14560 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14561
14562 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14563 AssertRCReturn(rc, rc);
14564
14565 /*
14566 * Raise #DB in the guest.
14567 *
14568 * It is important to reflect exactly what the VM-exit gave us (preserving the
14569 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14570 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14571 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14572 *
14573 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14574 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14575 */
14576 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14577 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14578 return VINF_SUCCESS;
14579 }
14580
14581 /*
14582 * Not a guest trap, must be a hypervisor related debug event then.
14583 * Update DR6 in case someone is interested in it.
14584 */
14585 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14586 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14587 CPUMSetHyperDR6(pVCpu, uDR6);
14588
14589 return rc;
14590}
14591
14592
14593/**
14594 * Hacks its way around the lovely mesa driver's backdoor accesses.
14595 *
14596 * @sa hmR0SvmHandleMesaDrvGp.
14597 */
14598static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14599{
14600 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14601 RT_NOREF(pCtx);
14602
14603 /* For now we'll just skip the instruction. */
14604 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14605}
14606
14607
14608/**
14609 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14610 * backdoor logging w/o checking what it is running inside.
14611 *
14612 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14613 * backdoor port and magic numbers loaded in registers.
14614 *
14615 * @returns true if it is, false if it isn't.
14616 * @sa hmR0SvmIsMesaDrvGp.
14617 */
14618DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14619{
14620 /* 0xed: IN eAX,dx */
14621 uint8_t abInstr[1];
14622 if (pVmxTransient->cbInstr != sizeof(abInstr))
14623 return false;
14624
14625 /* Check that it is #GP(0). */
14626 if (pVmxTransient->uExitIntErrorCode != 0)
14627 return false;
14628
14629 /* Check magic and port. */
14630 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14631 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14632 if (pCtx->rax != UINT32_C(0x564d5868))
14633 return false;
14634 if (pCtx->dx != UINT32_C(0x5658))
14635 return false;
14636
14637 /* Flat ring-3 CS. */
14638 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14639 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14640 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14641 if (pCtx->cs.Attr.n.u2Dpl != 3)
14642 return false;
14643 if (pCtx->cs.u64Base != 0)
14644 return false;
14645
14646 /* Check opcode. */
14647 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14648 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14649 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14650 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14651 if (RT_FAILURE(rc))
14652 return false;
14653 if (abInstr[0] != 0xed)
14654 return false;
14655
14656 return true;
14657}
14658
14659
14660/**
14661 * VM-exit exception handler for \#GP (General-protection exception).
14662 *
14663 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14664 */
14665static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14666{
14667 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14668 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14669
14670 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14671 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14672 if (pVmcsInfo->RealMode.fRealOnV86Active)
14673 { /* likely */ }
14674 else
14675 {
14676#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14677 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14678#endif
14679 /*
14680 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14681 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14682 */
14683 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14684 AssertRCReturn(rc, rc);
14685 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14686 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14687
14688 if ( pVmxTransient->fIsNestedGuest
14689 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14690 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14691 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14692 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14693 else
14694 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14695 return rc;
14696 }
14697
14698 Assert(CPUMIsGuestInRealModeEx(pCtx));
14699 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14700 Assert(!pVmxTransient->fIsNestedGuest);
14701
14702 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14703 AssertRCReturn(rc, rc);
14704
14705 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14706 if (rcStrict == VINF_SUCCESS)
14707 {
14708 if (!CPUMIsGuestInRealModeEx(pCtx))
14709 {
14710 /*
14711 * The guest is no longer in real-mode, check if we can continue executing the
14712 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14713 */
14714 pVmcsInfo->RealMode.fRealOnV86Active = false;
14715 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14716 {
14717 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14718 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14719 }
14720 else
14721 {
14722 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14723 rcStrict = VINF_EM_RESCHEDULE;
14724 }
14725 }
14726 else
14727 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14728 }
14729 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14730 {
14731 rcStrict = VINF_SUCCESS;
14732 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14733 }
14734 return VBOXSTRICTRC_VAL(rcStrict);
14735}
14736
14737
14738/**
14739 * VM-exit exception handler wrapper for all other exceptions that are not handled
14740 * by a specific handler.
14741 *
14742 * This simply re-injects the exception back into the VM without any special
14743 * processing.
14744 *
14745 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14746 */
14747static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14748{
14749 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14750
14751#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14752 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14753 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14754 ("uVector=%#x u32XcptBitmap=%#X32\n",
14755 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14756 NOREF(pVmcsInfo);
14757#endif
14758
14759 /*
14760 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14761 * would have been handled while checking exits due to event delivery.
14762 */
14763 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14764
14765#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14766 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14767 AssertRCReturn(rc, rc);
14768 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14769#endif
14770
14771#ifdef VBOX_WITH_STATISTICS
14772 switch (uVector)
14773 {
14774 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14775 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14776 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14777 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14778 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14779 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14780 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14781 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14782 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14783 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14784 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14785 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14786 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14787 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14788 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14789 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14790 default:
14791 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14792 break;
14793 }
14794#endif
14795
14796 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14797 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14798 NOREF(uVector);
14799
14800 /* Re-inject the original exception into the guest. */
14801 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14802 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14803 return VINF_SUCCESS;
14804}
14805
14806
14807/**
14808 * VM-exit exception handler for all exceptions (except NMIs!).
14809 *
14810 * @remarks This may be called for both guests and nested-guests. Take care to not
14811 * make assumptions and avoid doing anything that is not relevant when
14812 * executing a nested-guest (e.g., Mesa driver hacks).
14813 */
14814static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14815{
14816 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14817
14818 /*
14819 * If this VM-exit occurred while delivering an event through the guest IDT, take
14820 * action based on the return code and additional hints (e.g. for page-faults)
14821 * that will be updated in the VMX transient structure.
14822 */
14823 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14824 if (rcStrict == VINF_SUCCESS)
14825 {
14826 /*
14827 * If an exception caused a VM-exit due to delivery of an event, the original
14828 * event may have to be re-injected into the guest. We shall reinject it and
14829 * continue guest execution. However, page-fault is a complicated case and
14830 * needs additional processing done in hmR0VmxExitXcptPF().
14831 */
14832 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14833 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14834 if ( !pVCpu->hm.s.Event.fPending
14835 || uVector == X86_XCPT_PF)
14836 {
14837 switch (uVector)
14838 {
14839 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14840 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14841 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14842 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14843 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14844 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14845 default:
14846 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14847 }
14848 }
14849 /* else: inject pending event before resuming guest execution. */
14850 }
14851 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14852 {
14853 Assert(pVCpu->hm.s.Event.fPending);
14854 rcStrict = VINF_SUCCESS;
14855 }
14856
14857 return rcStrict;
14858}
14859/** @} */
14860
14861
14862/** @name VM-exit handlers.
14863 * @{
14864 */
14865/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14866/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14867/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14868
14869/**
14870 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14871 */
14872HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14873{
14874 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14875 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14876 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14877 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14878 return VINF_SUCCESS;
14879 return VINF_EM_RAW_INTERRUPT;
14880}
14881
14882
14883/**
14884 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14885 * VM-exit.
14886 */
14887HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14888{
14889 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14890 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14891
14892 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14893 AssertRCReturn(rc, rc);
14894
14895 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14896 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14897 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14898
14899 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14900 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14901 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14902 NOREF(pVmcsInfo);
14903
14904 VBOXSTRICTRC rcStrict;
14905 switch (uExitIntType)
14906 {
14907 /*
14908 * Host physical NMIs:
14909 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14910 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14911 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14912 *
14913 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14914 * See Intel spec. 27.5.5 "Updating Non-Register State".
14915 */
14916 case VMX_EXIT_INT_INFO_TYPE_NMI:
14917 {
14918 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14919 break;
14920 }
14921
14922 /*
14923 * Privileged software exceptions (#DB from ICEBP),
14924 * Software exceptions (#BP and #OF),
14925 * Hardware exceptions:
14926 * Process the required exceptions and resume guest execution if possible.
14927 */
14928 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14929 Assert(uVector == X86_XCPT_DB);
14930 RT_FALL_THRU();
14931 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14932 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14933 RT_FALL_THRU();
14934 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14935 {
14936 NOREF(uVector);
14937 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14938 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14939 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14940 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14941 AssertRCReturn(rc, rc);
14942
14943 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14944 break;
14945 }
14946
14947 default:
14948 {
14949 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14950 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14951 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14952 break;
14953 }
14954 }
14955
14956 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14957 return rcStrict;
14958}
14959
14960
14961/**
14962 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14963 */
14964HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14965{
14966 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14967
14968 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14969 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14970 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14971 AssertRCReturn(rc, rc);
14972
14973 /* Evaluate and deliver pending events and resume guest execution. */
14974 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14975 return VINF_SUCCESS;
14976}
14977
14978
14979/**
14980 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14981 */
14982HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14983{
14984 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14985
14986 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14987 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14988 {
14989 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14990 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14991 }
14992
14993 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14994
14995 /*
14996 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14997 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14998 */
14999 uint32_t fIntrState;
15000 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15001 AssertRCReturn(rc, rc);
15002 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
15003 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
15004 {
15005 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
15006 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
15007
15008 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
15009 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
15010 AssertRCReturn(rc, rc);
15011 }
15012
15013 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
15014 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
15015 AssertRCReturn(rc, rc);
15016
15017 /* Evaluate and deliver pending events and resume guest execution. */
15018 return VINF_SUCCESS;
15019}
15020
15021
15022/**
15023 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
15024 */
15025HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15026{
15027 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15028 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15029}
15030
15031
15032/**
15033 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
15034 */
15035HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15036{
15037 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15038 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15039}
15040
15041
15042/**
15043 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
15044 */
15045HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15046{
15047 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15048
15049 /*
15050 * Get the state we need and update the exit history entry.
15051 */
15052 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15053 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15054 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15055 AssertRCReturn(rc, rc);
15056
15057 VBOXSTRICTRC rcStrict;
15058 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15059 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
15060 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15061 if (!pExitRec)
15062 {
15063 /*
15064 * Regular CPUID instruction execution.
15065 */
15066 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
15067 if (rcStrict == VINF_SUCCESS)
15068 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15069 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15070 {
15071 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15072 rcStrict = VINF_SUCCESS;
15073 }
15074 }
15075 else
15076 {
15077 /*
15078 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15079 */
15080 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15081 AssertRCReturn(rc2, rc2);
15082
15083 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
15084 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
15085
15086 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15087 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15088
15089 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15090 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15091 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15092 }
15093 return rcStrict;
15094}
15095
15096
15097/**
15098 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
15099 */
15100HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15101{
15102 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15103
15104 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15105 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
15106 AssertRCReturn(rc, rc);
15107
15108 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
15109 return VINF_EM_RAW_EMULATE_INSTR;
15110
15111 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
15112 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15113}
15114
15115
15116/**
15117 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
15118 */
15119HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15120{
15121 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15122
15123 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15124 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15125 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15126 AssertRCReturn(rc, rc);
15127
15128 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
15129 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15130 {
15131 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15132 we must reset offsetting on VM-entry. See @bugref{6634}. */
15133 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15134 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15135 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15136 }
15137 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15138 {
15139 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15140 rcStrict = VINF_SUCCESS;
15141 }
15142 return rcStrict;
15143}
15144
15145
15146/**
15147 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
15148 */
15149HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15150{
15151 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15152
15153 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15154 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
15155 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15156 AssertRCReturn(rc, rc);
15157
15158 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
15159 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15160 {
15161 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15162 we must reset offsetting on VM-reentry. See @bugref{6634}. */
15163 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15164 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15165 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15166 }
15167 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15168 {
15169 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15170 rcStrict = VINF_SUCCESS;
15171 }
15172 return rcStrict;
15173}
15174
15175
15176/**
15177 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
15178 */
15179HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15180{
15181 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15182
15183 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15184 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
15185 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
15186 AssertRCReturn(rc, rc);
15187
15188 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15189 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
15190 if (RT_LIKELY(rc == VINF_SUCCESS))
15191 {
15192 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15193 Assert(pVmxTransient->cbInstr == 2);
15194 }
15195 else
15196 {
15197 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
15198 rc = VERR_EM_INTERPRETER;
15199 }
15200 return rc;
15201}
15202
15203
15204/**
15205 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
15206 */
15207HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15208{
15209 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15210
15211 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
15212 if (EMAreHypercallInstructionsEnabled(pVCpu))
15213 {
15214 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15215 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
15216 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
15217 AssertRCReturn(rc, rc);
15218
15219 /* Perform the hypercall. */
15220 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
15221 if (rcStrict == VINF_SUCCESS)
15222 {
15223 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15224 AssertRCReturn(rc, rc);
15225 }
15226 else
15227 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15228 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15229 || RT_FAILURE(rcStrict));
15230
15231 /* If the hypercall changes anything other than guest's general-purpose registers,
15232 we would need to reload the guest changed bits here before VM-entry. */
15233 }
15234 else
15235 Log4Func(("Hypercalls not enabled\n"));
15236
15237 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15238 if (RT_FAILURE(rcStrict))
15239 {
15240 hmR0VmxSetPendingXcptUD(pVCpu);
15241 rcStrict = VINF_SUCCESS;
15242 }
15243
15244 return rcStrict;
15245}
15246
15247
15248/**
15249 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15250 */
15251HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15252{
15253 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15254 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15255
15256 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15257 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15258 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15259 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15260 AssertRCReturn(rc, rc);
15261
15262 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15263
15264 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15265 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15266 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15267 {
15268 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15269 rcStrict = VINF_SUCCESS;
15270 }
15271 else
15272 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15273 VBOXSTRICTRC_VAL(rcStrict)));
15274 return rcStrict;
15275}
15276
15277
15278/**
15279 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15280 */
15281HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15282{
15283 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15284
15285 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15286 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15287 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15288 AssertRCReturn(rc, rc);
15289
15290 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15291 if (rcStrict == VINF_SUCCESS)
15292 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15293 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15294 {
15295 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15296 rcStrict = VINF_SUCCESS;
15297 }
15298
15299 return rcStrict;
15300}
15301
15302
15303/**
15304 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15305 */
15306HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15307{
15308 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15309
15310 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15311 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15312 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15313 AssertRCReturn(rc, rc);
15314
15315 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15316 if (RT_SUCCESS(rcStrict))
15317 {
15318 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15319 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15320 rcStrict = VINF_SUCCESS;
15321 }
15322
15323 return rcStrict;
15324}
15325
15326
15327/**
15328 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15329 * VM-exit.
15330 */
15331HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15332{
15333 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15334 return VINF_EM_RESET;
15335}
15336
15337
15338/**
15339 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15340 */
15341HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15342{
15343 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15344
15345 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15346 AssertRCReturn(rc, rc);
15347
15348 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15349 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15350 rc = VINF_SUCCESS;
15351 else
15352 rc = VINF_EM_HALT;
15353
15354 if (rc != VINF_SUCCESS)
15355 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15356 return rc;
15357}
15358
15359
15360/**
15361 * VM-exit handler for instructions that result in a \#UD exception delivered to
15362 * the guest.
15363 */
15364HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15365{
15366 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15367 hmR0VmxSetPendingXcptUD(pVCpu);
15368 return VINF_SUCCESS;
15369}
15370
15371
15372/**
15373 * VM-exit handler for expiry of the VMX-preemption timer.
15374 */
15375HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15376{
15377 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15378
15379 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15380 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15381
15382 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15383 PVM pVM = pVCpu->CTX_SUFF(pVM);
15384 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15385 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15386 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15387}
15388
15389
15390/**
15391 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15392 */
15393HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15394{
15395 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15396
15397 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15398 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15399 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15400 AssertRCReturn(rc, rc);
15401
15402 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15403 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15404 : HM_CHANGED_RAISED_XCPT_MASK);
15405
15406 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15407 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15408
15409 return rcStrict;
15410}
15411
15412
15413/**
15414 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15415 */
15416HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15417{
15418 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15419 /** @todo Use VM-exit instruction information. */
15420 return VERR_EM_INTERPRETER;
15421}
15422
15423
15424/**
15425 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15426 * VM-exit.
15427 */
15428HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15429{
15430 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15431 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15432 AssertRCReturn(rc, rc);
15433
15434 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15435 if (RT_FAILURE(rc))
15436 return rc;
15437
15438 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15439 NOREF(uInvalidReason);
15440
15441#ifdef VBOX_STRICT
15442 uint32_t fIntrState;
15443 RTHCUINTREG uHCReg;
15444 uint64_t u64Val;
15445 uint32_t u32Val;
15446 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15447 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15448 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15449 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15450 AssertRCReturn(rc, rc);
15451
15452 Log4(("uInvalidReason %u\n", uInvalidReason));
15453 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15454 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15455 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15456 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15457
15458 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15459 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15460 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15461 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15462 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15463 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15464 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15465 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15466 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15467 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15468 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15469 {
15470 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15471 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15472 }
15473
15474 hmR0DumpRegs(pVCpu);
15475#endif
15476
15477 return VERR_VMX_INVALID_GUEST_STATE;
15478}
15479
15480/**
15481 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15482 */
15483HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15484{
15485 /*
15486 * Cummulative notes of all recognized but unexpected VM-exits.
15487 *
15488 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15489 * nested-paging is used.
15490 *
15491 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15492 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15493 * this function (and thereby stop VM execution) for handling such instructions.
15494 *
15495 *
15496 * VMX_EXIT_INIT_SIGNAL:
15497 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15498 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15499 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15500 *
15501 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15502 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15503 * See Intel spec. "23.8 Restrictions on VMX operation".
15504 *
15505 * VMX_EXIT_SIPI:
15506 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15507 * activity state is used. We don't make use of it as our guests don't have direct
15508 * access to the host local APIC.
15509 *
15510 * See Intel spec. 25.3 "Other Causes of VM-exits".
15511 *
15512 * VMX_EXIT_IO_SMI:
15513 * VMX_EXIT_SMI:
15514 * This can only happen if we support dual-monitor treatment of SMI, which can be
15515 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15516 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15517 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15518 *
15519 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15520 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15521 *
15522 * VMX_EXIT_ERR_MSR_LOAD:
15523 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15524 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15525 * execution.
15526 *
15527 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15528 *
15529 * VMX_EXIT_ERR_MACHINE_CHECK:
15530 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15531 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15532 * #MC exception abort class exception is raised. We thus cannot assume a
15533 * reasonable chance of continuing any sort of execution and we bail.
15534 *
15535 * See Intel spec. 15.1 "Machine-check Architecture".
15536 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15537 *
15538 * VMX_EXIT_PML_FULL:
15539 * VMX_EXIT_VIRTUALIZED_EOI:
15540 * VMX_EXIT_APIC_WRITE:
15541 * We do not currently support any of these features and thus they are all unexpected
15542 * VM-exits.
15543 *
15544 * VMX_EXIT_GDTR_IDTR_ACCESS:
15545 * VMX_EXIT_LDTR_TR_ACCESS:
15546 * VMX_EXIT_RDRAND:
15547 * VMX_EXIT_RSM:
15548 * VMX_EXIT_VMFUNC:
15549 * VMX_EXIT_ENCLS:
15550 * VMX_EXIT_RDSEED:
15551 * VMX_EXIT_XSAVES:
15552 * VMX_EXIT_XRSTORS:
15553 * VMX_EXIT_UMWAIT:
15554 * VMX_EXIT_TPAUSE:
15555 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15556 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15557 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15558 *
15559 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15560 */
15561 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15562 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15563 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15564}
15565
15566
15567/**
15568 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15569 */
15570HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15571{
15572 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15573
15574 /** @todo Optimize this: We currently drag in in the whole MSR state
15575 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15576 * MSRs required. That would require changes to IEM and possibly CPUM too.
15577 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15578 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15579 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15580 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15581 switch (idMsr)
15582 {
15583 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15584 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15585 }
15586
15587 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15588 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15589 AssertRCReturn(rc, rc);
15590
15591 Log4Func(("ecx=%#RX32\n", idMsr));
15592
15593#ifdef VBOX_STRICT
15594 Assert(!pVmxTransient->fIsNestedGuest);
15595 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15596 {
15597 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15598 && idMsr != MSR_K6_EFER)
15599 {
15600 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15601 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15602 }
15603 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15604 {
15605 Assert(pVmcsInfo->pvMsrBitmap);
15606 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15607 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15608 {
15609 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15610 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15611 }
15612 }
15613 }
15614#endif
15615
15616 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15617 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15618 if (rcStrict == VINF_SUCCESS)
15619 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15620 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15621 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15622 {
15623 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15624 rcStrict = VINF_SUCCESS;
15625 }
15626 else
15627 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15628
15629 return rcStrict;
15630}
15631
15632
15633/**
15634 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15635 */
15636HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15637{
15638 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15639
15640 /** @todo Optimize this: We currently drag in in the whole MSR state
15641 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15642 * MSRs required. That would require changes to IEM and possibly CPUM too.
15643 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15644 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15645 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15646
15647 /*
15648 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15649 * Although we don't need to fetch the base as it will be overwritten shortly, while
15650 * loading guest-state we would also load the entire segment register including limit
15651 * and attributes and thus we need to load them here.
15652 */
15653 switch (idMsr)
15654 {
15655 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15656 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15657 }
15658
15659 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15660 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15661 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15662 AssertRCReturn(rc, rc);
15663
15664 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15665
15666 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15667 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15668
15669 if (rcStrict == VINF_SUCCESS)
15670 {
15671 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15672
15673 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15674 if ( idMsr == MSR_IA32_APICBASE
15675 || ( idMsr >= MSR_IA32_X2APIC_START
15676 && idMsr <= MSR_IA32_X2APIC_END))
15677 {
15678 /*
15679 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15680 * When full APIC register virtualization is implemented we'll have to make
15681 * sure APIC state is saved from the VMCS before IEM changes it.
15682 */
15683 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15684 }
15685 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15686 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15687 else if (idMsr == MSR_K6_EFER)
15688 {
15689 /*
15690 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15691 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15692 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15693 */
15694 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15695 }
15696
15697 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15698 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15699 {
15700 switch (idMsr)
15701 {
15702 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15703 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15704 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15705 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15706 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15707 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15708 default:
15709 {
15710 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15711 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15712 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15713 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15714 break;
15715 }
15716 }
15717 }
15718#ifdef VBOX_STRICT
15719 else
15720 {
15721 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15722 switch (idMsr)
15723 {
15724 case MSR_IA32_SYSENTER_CS:
15725 case MSR_IA32_SYSENTER_EIP:
15726 case MSR_IA32_SYSENTER_ESP:
15727 case MSR_K8_FS_BASE:
15728 case MSR_K8_GS_BASE:
15729 {
15730 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15731 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15732 }
15733
15734 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15735 default:
15736 {
15737 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15738 {
15739 /* EFER MSR writes are always intercepted. */
15740 if (idMsr != MSR_K6_EFER)
15741 {
15742 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15743 idMsr));
15744 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15745 }
15746 }
15747
15748 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15749 {
15750 Assert(pVmcsInfo->pvMsrBitmap);
15751 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15752 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15753 {
15754 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15755 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15756 }
15757 }
15758 break;
15759 }
15760 }
15761 }
15762#endif /* VBOX_STRICT */
15763 }
15764 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15765 {
15766 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15767 rcStrict = VINF_SUCCESS;
15768 }
15769 else
15770 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15771
15772 return rcStrict;
15773}
15774
15775
15776/**
15777 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15778 */
15779HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15780{
15781 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15782
15783 /** @todo The guest has likely hit a contended spinlock. We might want to
15784 * poke a schedule different guest VCPU. */
15785 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15786 if (RT_SUCCESS(rc))
15787 return VINF_EM_RAW_INTERRUPT;
15788
15789 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15790 return rc;
15791}
15792
15793
15794/**
15795 * VM-exit handler for when the TPR value is lowered below the specified
15796 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15797 */
15798HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15799{
15800 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15801 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15802
15803 /*
15804 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15805 * We'll re-evaluate pending interrupts and inject them before the next VM
15806 * entry so we can just continue execution here.
15807 */
15808 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15809 return VINF_SUCCESS;
15810}
15811
15812
15813/**
15814 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15815 * VM-exit.
15816 *
15817 * @retval VINF_SUCCESS when guest execution can continue.
15818 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15819 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15820 * incompatible guest state for VMX execution (real-on-v86 case).
15821 */
15822HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15823{
15824 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15825 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15826
15827 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15828 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15829 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15830 AssertRCReturn(rc, rc);
15831
15832 VBOXSTRICTRC rcStrict;
15833 PVM pVM = pVCpu->CTX_SUFF(pVM);
15834 uint64_t const uExitQual = pVmxTransient->uExitQual;
15835 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15836 switch (uAccessType)
15837 {
15838 /*
15839 * MOV to CRx.
15840 */
15841 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15842 {
15843 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15844 AssertRCReturn(rc, rc);
15845
15846 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15847 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15848 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15849 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15850
15851 /*
15852 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15853 * - When nested paging isn't used.
15854 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15855 * - We are executing in the VM debug loop.
15856 */
15857 Assert( iCrReg != 3
15858 || !pVM->hm.s.fNestedPaging
15859 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15860 || pVCpu->hm.s.fUsingDebugLoop);
15861
15862 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15863 Assert( iCrReg != 8
15864 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15865
15866 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15867 AssertMsg( rcStrict == VINF_SUCCESS
15868 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15869
15870 /*
15871 * This is a kludge for handling switches back to real mode when we try to use
15872 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15873 * deal with special selector values, so we have to return to ring-3 and run
15874 * there till the selector values are V86 mode compatible.
15875 *
15876 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15877 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15878 * this function.
15879 */
15880 if ( iCrReg == 0
15881 && rcStrict == VINF_SUCCESS
15882 && !pVM->hm.s.vmx.fUnrestrictedGuest
15883 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15884 && (uOldCr0 & X86_CR0_PE)
15885 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15886 {
15887 /** @todo Check selectors rather than returning all the time. */
15888 Assert(!pVmxTransient->fIsNestedGuest);
15889 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15890 rcStrict = VINF_EM_RESCHEDULE_REM;
15891 }
15892 break;
15893 }
15894
15895 /*
15896 * MOV from CRx.
15897 */
15898 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15899 {
15900 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15901 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15902
15903 /*
15904 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15905 * - When nested paging isn't used.
15906 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15907 * - We are executing in the VM debug loop.
15908 */
15909 Assert( iCrReg != 3
15910 || !pVM->hm.s.fNestedPaging
15911 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15912 || pVCpu->hm.s.fUsingDebugLoop);
15913
15914 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15915 Assert( iCrReg != 8
15916 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15917
15918 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15919 break;
15920 }
15921
15922 /*
15923 * CLTS (Clear Task-Switch Flag in CR0).
15924 */
15925 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15926 {
15927 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15928 break;
15929 }
15930
15931 /*
15932 * LMSW (Load Machine-Status Word into CR0).
15933 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15934 */
15935 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15936 {
15937 RTGCPTR GCPtrEffDst;
15938 uint8_t const cbInstr = pVmxTransient->cbInstr;
15939 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15940 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15941 if (fMemOperand)
15942 {
15943 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15944 AssertRCReturn(rc, rc);
15945 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15946 }
15947 else
15948 GCPtrEffDst = NIL_RTGCPTR;
15949 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15950 break;
15951 }
15952
15953 default:
15954 {
15955 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15956 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15957 }
15958 }
15959
15960 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15961 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15962 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15963
15964 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15965 NOREF(pVM);
15966 return rcStrict;
15967}
15968
15969
15970/**
15971 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15972 * VM-exit.
15973 */
15974HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15975{
15976 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15977 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15978
15979 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15980 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15981 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15982 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15983 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15984 | CPUMCTX_EXTRN_EFER);
15985 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15986 AssertRCReturn(rc, rc);
15987
15988 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15989 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15990 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15991 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15992 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15993 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15994 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15995 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15996
15997 /*
15998 * Update exit history to see if this exit can be optimized.
15999 */
16000 VBOXSTRICTRC rcStrict;
16001 PCEMEXITREC pExitRec = NULL;
16002 if ( !fGstStepping
16003 && !fDbgStepping)
16004 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16005 !fIOString
16006 ? !fIOWrite
16007 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
16008 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
16009 : !fIOWrite
16010 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
16011 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
16012 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16013 if (!pExitRec)
16014 {
16015 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16016 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
16017
16018 uint32_t const cbValue = s_aIOSizes[uIOSize];
16019 uint32_t const cbInstr = pVmxTransient->cbInstr;
16020 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
16021 PVM pVM = pVCpu->CTX_SUFF(pVM);
16022 if (fIOString)
16023 {
16024 /*
16025 * INS/OUTS - I/O String instruction.
16026 *
16027 * Use instruction-information if available, otherwise fall back on
16028 * interpreting the instruction.
16029 */
16030 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
16031 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
16032 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
16033 if (fInsOutsInfo)
16034 {
16035 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16036 AssertRCReturn(rc2, rc2);
16037 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
16038 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
16039 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
16040 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
16041 if (fIOWrite)
16042 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
16043 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
16044 else
16045 {
16046 /*
16047 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
16048 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
16049 * See Intel Instruction spec. for "INS".
16050 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
16051 */
16052 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
16053 }
16054 }
16055 else
16056 rcStrict = IEMExecOne(pVCpu);
16057
16058 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
16059 fUpdateRipAlready = true;
16060 }
16061 else
16062 {
16063 /*
16064 * IN/OUT - I/O instruction.
16065 */
16066 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
16067 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
16068 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
16069 if (fIOWrite)
16070 {
16071 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
16072 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
16073 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16074 && !pCtx->eflags.Bits.u1TF)
16075 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
16076 }
16077 else
16078 {
16079 uint32_t u32Result = 0;
16080 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
16081 if (IOM_SUCCESS(rcStrict))
16082 {
16083 /* Save result of I/O IN instr. in AL/AX/EAX. */
16084 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
16085 }
16086 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16087 && !pCtx->eflags.Bits.u1TF)
16088 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
16089 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
16090 }
16091 }
16092
16093 if (IOM_SUCCESS(rcStrict))
16094 {
16095 if (!fUpdateRipAlready)
16096 {
16097 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
16098 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
16099 }
16100
16101 /*
16102 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
16103 * while booting Fedora 17 64-bit guest.
16104 *
16105 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
16106 */
16107 if (fIOString)
16108 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
16109
16110 /*
16111 * If any I/O breakpoints are armed, we need to check if one triggered
16112 * and take appropriate action.
16113 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
16114 */
16115 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
16116 AssertRCReturn(rc, rc);
16117
16118 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
16119 * execution engines about whether hyper BPs and such are pending. */
16120 uint32_t const uDr7 = pCtx->dr[7];
16121 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
16122 && X86_DR7_ANY_RW_IO(uDr7)
16123 && (pCtx->cr4 & X86_CR4_DE))
16124 || DBGFBpIsHwIoArmed(pVM)))
16125 {
16126 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
16127
16128 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
16129 VMMRZCallRing3Disable(pVCpu);
16130 HM_DISABLE_PREEMPT(pVCpu);
16131
16132 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
16133
16134 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
16135 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
16136 {
16137 /* Raise #DB. */
16138 if (fIsGuestDbgActive)
16139 ASMSetDR6(pCtx->dr[6]);
16140 if (pCtx->dr[7] != uDr7)
16141 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
16142
16143 hmR0VmxSetPendingXcptDB(pVCpu);
16144 }
16145 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
16146 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
16147 else if ( rcStrict2 != VINF_SUCCESS
16148 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
16149 rcStrict = rcStrict2;
16150 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
16151
16152 HM_RESTORE_PREEMPT();
16153 VMMRZCallRing3Enable(pVCpu);
16154 }
16155 }
16156
16157#ifdef VBOX_STRICT
16158 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16159 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
16160 Assert(!fIOWrite);
16161 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16162 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
16163 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
16164 Assert(fIOWrite);
16165 else
16166 {
16167# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
16168 * statuses, that the VMM device and some others may return. See
16169 * IOM_SUCCESS() for guidance. */
16170 AssertMsg( RT_FAILURE(rcStrict)
16171 || rcStrict == VINF_SUCCESS
16172 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
16173 || rcStrict == VINF_EM_DBG_BREAKPOINT
16174 || rcStrict == VINF_EM_RAW_GUEST_TRAP
16175 || rcStrict == VINF_EM_RAW_TO_R3
16176 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16177# endif
16178 }
16179#endif
16180 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
16181 }
16182 else
16183 {
16184 /*
16185 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
16186 */
16187 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16188 AssertRCReturn(rc2, rc2);
16189 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
16190 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
16191 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
16192 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16193 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
16194 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
16195
16196 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16197 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16198
16199 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16200 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16201 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16202 }
16203 return rcStrict;
16204}
16205
16206
16207/**
16208 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16209 * VM-exit.
16210 */
16211HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16212{
16213 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16214
16215 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16216 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16217 AssertRCReturn(rc, rc);
16218 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16219 {
16220 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16221 AssertRCReturn(rc, rc);
16222 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16223 {
16224 uint32_t uErrCode;
16225 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16226 {
16227 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16228 AssertRCReturn(rc, rc);
16229 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16230 }
16231 else
16232 uErrCode = 0;
16233
16234 RTGCUINTPTR GCPtrFaultAddress;
16235 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16236 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16237 else
16238 GCPtrFaultAddress = 0;
16239
16240 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16241 AssertRCReturn(rc, rc);
16242
16243 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16244 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16245
16246 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16247 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16248 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16249 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16250 }
16251 }
16252
16253 /* Fall back to the interpreter to emulate the task-switch. */
16254 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16255 return VERR_EM_INTERPRETER;
16256}
16257
16258
16259/**
16260 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16261 */
16262HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16263{
16264 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16265
16266 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16267 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16268 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16269 AssertRCReturn(rc, rc);
16270 return VINF_EM_DBG_STEPPED;
16271}
16272
16273
16274/**
16275 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16276 */
16277HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16278{
16279 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16280 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16281
16282 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16283 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16284 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16285 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16286 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16287 AssertRCReturn(rc, rc);
16288
16289 /*
16290 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16291 */
16292 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16293 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16294 {
16295 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16296 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16297 {
16298 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16299 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16300 }
16301 }
16302 else
16303 {
16304 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16305 return rcStrict;
16306 }
16307
16308 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16309 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16310 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16311 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16312 AssertRCReturn(rc, rc);
16313
16314 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16315 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16316 switch (uAccessType)
16317 {
16318 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16319 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16320 {
16321 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16322 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16323 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16324
16325 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16326 GCPhys &= PAGE_BASE_GC_MASK;
16327 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16328 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16329 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16330
16331 PVM pVM = pVCpu->CTX_SUFF(pVM);
16332 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16333 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
16334 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16335 CPUMCTX2CORE(pCtx), GCPhys);
16336 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16337 if ( rcStrict == VINF_SUCCESS
16338 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16339 || rcStrict == VERR_PAGE_NOT_PRESENT)
16340 {
16341 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16342 | HM_CHANGED_GUEST_APIC_TPR);
16343 rcStrict = VINF_SUCCESS;
16344 }
16345 break;
16346 }
16347
16348 default:
16349 {
16350 Log4Func(("uAccessType=%#x\n", uAccessType));
16351 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16352 break;
16353 }
16354 }
16355
16356 if (rcStrict != VINF_SUCCESS)
16357 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16358 return rcStrict;
16359}
16360
16361
16362/**
16363 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16364 * VM-exit.
16365 */
16366HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16367{
16368 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16369 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16370
16371 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
16372 if (!pVmxTransient->fIsNestedGuest)
16373 {
16374 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16375 if (pVmxTransient->fWasGuestDebugStateActive)
16376 {
16377 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16378 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16379 }
16380
16381 if ( !pVCpu->hm.s.fSingleInstruction
16382 && !pVmxTransient->fWasHyperDebugStateActive)
16383 {
16384 Assert(!DBGFIsStepping(pVCpu));
16385 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16386
16387 /* Don't intercept MOV DRx any more. */
16388 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16389 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16390 AssertRCReturn(rc, rc);
16391
16392 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16393 VMMRZCallRing3Disable(pVCpu);
16394 HM_DISABLE_PREEMPT(pVCpu);
16395
16396 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16397 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16398 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16399
16400 HM_RESTORE_PREEMPT();
16401 VMMRZCallRing3Enable(pVCpu);
16402
16403#ifdef VBOX_WITH_STATISTICS
16404 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16405 AssertRCReturn(rc, rc);
16406 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16407 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16408 else
16409 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16410#endif
16411 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16412 return VINF_SUCCESS;
16413 }
16414 }
16415
16416 /*
16417 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16418 * The EFER MSR is always up-to-date.
16419 * Update the segment registers and DR7 from the CPU.
16420 */
16421 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16422 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16423 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16424 AssertRCReturn(rc, rc);
16425 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16426
16427 PVM pVM = pVCpu->CTX_SUFF(pVM);
16428 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16429 {
16430 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16431 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16432 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16433 if (RT_SUCCESS(rc))
16434 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16435 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16436 }
16437 else
16438 {
16439 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16440 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16441 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16442 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16443 }
16444
16445 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16446 if (RT_SUCCESS(rc))
16447 {
16448 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16449 AssertRCReturn(rc2, rc2);
16450 return VINF_SUCCESS;
16451 }
16452 return rc;
16453}
16454
16455
16456/**
16457 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16458 * Conditional VM-exit.
16459 */
16460HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16461{
16462 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16463 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16464
16465 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16466 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16467 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16468 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16469 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16470 AssertRCReturn(rc, rc);
16471
16472 /*
16473 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16474 */
16475 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16476 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16477 {
16478 /*
16479 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16480 * instruction emulation to inject the original event. Otherwise, injecting the original event
16481 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16482 */
16483 if (!pVCpu->hm.s.Event.fPending)
16484 { /* likely */ }
16485 else
16486 {
16487 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16488#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16489 /** @todo NSTVMX: Think about how this should be handled. */
16490 if (pVmxTransient->fIsNestedGuest)
16491 return VERR_VMX_IPE_3;
16492#endif
16493 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16494 }
16495 }
16496 else
16497 {
16498 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16499 return rcStrict;
16500 }
16501
16502 /*
16503 * Get sufficent state and update the exit history entry.
16504 */
16505 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16506 rc = hmR0VmxReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
16507 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16508 AssertRCReturn(rc, rc);
16509
16510 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16511 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16512 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16513 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16514 if (!pExitRec)
16515 {
16516 /*
16517 * If we succeed, resume guest execution.
16518 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16519 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16520 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16521 * weird case. See @bugref{6043}.
16522 */
16523 PVM pVM = pVCpu->CTX_SUFF(pVM);
16524 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16525 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16526 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16527 if ( rcStrict == VINF_SUCCESS
16528 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16529 || rcStrict == VERR_PAGE_NOT_PRESENT)
16530 {
16531 /* Successfully handled MMIO operation. */
16532 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16533 | HM_CHANGED_GUEST_APIC_TPR);
16534 rcStrict = VINF_SUCCESS;
16535 }
16536 }
16537 else
16538 {
16539 /*
16540 * Frequent exit or something needing probing. Call EMHistoryExec.
16541 */
16542 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16543 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16544
16545 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16546 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16547
16548 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16549 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16550 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16551 }
16552 return rcStrict;
16553}
16554
16555
16556/**
16557 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16558 * VM-exit.
16559 */
16560HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16561{
16562 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16563 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16564
16565 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16566 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16567 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16568 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16569 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16570 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16571 AssertRCReturn(rc, rc);
16572
16573 /*
16574 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16575 */
16576 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16577 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16578 {
16579 /*
16580 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16581 * we shall resolve the nested #PF and re-inject the original event.
16582 */
16583 if (pVCpu->hm.s.Event.fPending)
16584 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16585 }
16586 else
16587 {
16588 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16589 return rcStrict;
16590 }
16591
16592 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16593 rc = hmR0VmxReadGuestPhysicalAddrVmcs(pVCpu, pVmxTransient);
16594 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16595 AssertRCReturn(rc, rc);
16596
16597 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
16598 uint64_t const uExitQual = pVmxTransient->uExitQual;
16599 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16600
16601 RTGCUINT uErrorCode = 0;
16602 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16603 uErrorCode |= X86_TRAP_PF_ID;
16604 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16605 uErrorCode |= X86_TRAP_PF_RW;
16606 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16607 uErrorCode |= X86_TRAP_PF_P;
16608
16609 PVM pVM = pVCpu->CTX_SUFF(pVM);
16610 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16611 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16612
16613 /*
16614 * Handle the pagefault trap for the nested shadow table.
16615 */
16616 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16617 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16618 TRPMResetTrap(pVCpu);
16619
16620 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16621 if ( rcStrict == VINF_SUCCESS
16622 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16623 || rcStrict == VERR_PAGE_NOT_PRESENT)
16624 {
16625 /* Successfully synced our nested page tables. */
16626 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16627 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16628 return VINF_SUCCESS;
16629 }
16630
16631 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16632 return rcStrict;
16633}
16634
16635
16636#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16637/**
16638 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16639 */
16640HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16641{
16642 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16643
16644 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16645 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16646 | CPUMCTX_EXTRN_HWVIRT
16647 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16648 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16649 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16650 AssertRCReturn(rc, rc);
16651
16652 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16653
16654 VMXVEXITINFO ExitInfo;
16655 RT_ZERO(ExitInfo);
16656 ExitInfo.uReason = pVmxTransient->uExitReason;
16657 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16658 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16659 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16660 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16661
16662 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16663 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16664 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16665 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16666 {
16667 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16668 rcStrict = VINF_SUCCESS;
16669 }
16670 return rcStrict;
16671}
16672
16673
16674/**
16675 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16676 */
16677HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16678{
16679 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16680
16681 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16682 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16683 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16684 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16685 AssertRCReturn(rc, rc);
16686
16687 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16688
16689 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16690 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16691 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16692 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16693 {
16694 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16695 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16696 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16697 }
16698 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16699 return rcStrict;
16700}
16701
16702
16703/**
16704 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16705 */
16706HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16707{
16708 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16709
16710 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16711 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16712 | CPUMCTX_EXTRN_HWVIRT
16713 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16714 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16715 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16716 AssertRCReturn(rc, rc);
16717
16718 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16719
16720 VMXVEXITINFO ExitInfo;
16721 RT_ZERO(ExitInfo);
16722 ExitInfo.uReason = pVmxTransient->uExitReason;
16723 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16724 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16725 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16726 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16727
16728 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16729 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16730 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16731 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16732 {
16733 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16734 rcStrict = VINF_SUCCESS;
16735 }
16736 return rcStrict;
16737}
16738
16739
16740/**
16741 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16742 */
16743HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16744{
16745 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16746
16747 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16748 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16749 | CPUMCTX_EXTRN_HWVIRT
16750 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16751 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16752 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16753 AssertRCReturn(rc, rc);
16754
16755 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16756
16757 VMXVEXITINFO ExitInfo;
16758 RT_ZERO(ExitInfo);
16759 ExitInfo.uReason = pVmxTransient->uExitReason;
16760 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16761 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16762 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16763 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16764
16765 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16766 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16767 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16768 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16769 {
16770 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16771 rcStrict = VINF_SUCCESS;
16772 }
16773 return rcStrict;
16774}
16775
16776
16777/**
16778 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16779 */
16780HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16781{
16782 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16783
16784 /*
16785 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16786 * thus might not need to import the shadow VMCS state, it's safer just in case
16787 * code elsewhere dares look at unsynced VMCS fields.
16788 */
16789 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16790 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16791 | CPUMCTX_EXTRN_HWVIRT
16792 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16793 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16794 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16795 AssertRCReturn(rc, rc);
16796
16797 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16798
16799 VMXVEXITINFO ExitInfo;
16800 RT_ZERO(ExitInfo);
16801 ExitInfo.uReason = pVmxTransient->uExitReason;
16802 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16803 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16804 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16805 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16806 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16807
16808 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16809 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16810 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16811 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16812 {
16813 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16814 rcStrict = VINF_SUCCESS;
16815 }
16816 return rcStrict;
16817}
16818
16819
16820/**
16821 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16822 */
16823HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16824{
16825 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16826
16827 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16828 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16829 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16830 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16831 AssertRCReturn(rc, rc);
16832
16833 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16834
16835 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16836 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16837 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16838 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16839 {
16840 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16841 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16842 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16843 }
16844 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16845 return rcStrict;
16846}
16847
16848
16849/**
16850 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16851 */
16852HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16853{
16854 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16855
16856 /*
16857 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16858 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16859 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16860 */
16861 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16862 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16863 | CPUMCTX_EXTRN_HWVIRT
16864 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16865 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16866 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16867 AssertRCReturn(rc, rc);
16868
16869 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16870
16871 VMXVEXITINFO ExitInfo;
16872 RT_ZERO(ExitInfo);
16873 ExitInfo.uReason = pVmxTransient->uExitReason;
16874 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16875 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16876 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16877 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16878 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16879
16880 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16881 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16882 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16883 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16884 {
16885 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16886 rcStrict = VINF_SUCCESS;
16887 }
16888 return rcStrict;
16889}
16890
16891
16892/**
16893 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16894 */
16895HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16896{
16897 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16898
16899 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16900 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16901 | CPUMCTX_EXTRN_HWVIRT
16902 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16903 AssertRCReturn(rc, rc);
16904
16905 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16906
16907 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16908 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16909 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16910 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16911 {
16912 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16913 rcStrict = VINF_SUCCESS;
16914 }
16915 return rcStrict;
16916}
16917
16918
16919/**
16920 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16921 */
16922HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16923{
16924 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16925
16926 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16927 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16928 | CPUMCTX_EXTRN_HWVIRT
16929 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16930 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16931 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16932 AssertRCReturn(rc, rc);
16933
16934 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16935
16936 VMXVEXITINFO ExitInfo;
16937 RT_ZERO(ExitInfo);
16938 ExitInfo.uReason = pVmxTransient->uExitReason;
16939 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16940 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16941 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16942 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16943
16944 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16945 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16946 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16947 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16948 {
16949 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16950 rcStrict = VINF_SUCCESS;
16951 }
16952 return rcStrict;
16953}
16954
16955
16956/**
16957 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16958 */
16959HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16960{
16961 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16962
16963 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16964 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16965 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16966 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16967 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16968 AssertRCReturn(rc, rc);
16969
16970 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16971
16972 VMXVEXITINFO ExitInfo;
16973 RT_ZERO(ExitInfo);
16974 ExitInfo.uReason = pVmxTransient->uExitReason;
16975 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16976 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16977 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16978 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16979
16980 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16981 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16982 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16983 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16984 {
16985 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16986 rcStrict = VINF_SUCCESS;
16987 }
16988 return rcStrict;
16989}
16990#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16991/** @} */
16992
16993
16994#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16995/** @name Nested-guest VM-exit handlers.
16996 * @{
16997 */
16998/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16999/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
17000/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
17001
17002/**
17003 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
17004 * Conditional VM-exit.
17005 */
17006HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17007{
17008 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17009
17010 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
17011 AssertRCReturn(rc, rc);
17012
17013 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
17014 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
17015 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
17016
17017 switch (uExitIntType)
17018 {
17019 /*
17020 * Physical NMIs:
17021 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
17022 */
17023 case VMX_EXIT_INT_INFO_TYPE_NMI:
17024 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
17025
17026 /*
17027 * Hardware exceptions,
17028 * Software exceptions,
17029 * Privileged software exceptions:
17030 * Figure out if the exception must be delivered to the guest or the nested-guest.
17031 */
17032 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
17033 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
17034 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
17035 {
17036 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
17037 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17038 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17039 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17040 AssertRCReturn(rc, rc);
17041
17042 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17043 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
17044 pVmxTransient->uExitIntErrorCode);
17045 if (fIntercept)
17046 {
17047 /* Exit qualification is required for debug and page-fault exceptions. */
17048 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17049 AssertRCReturn(rc, rc);
17050
17051 /*
17052 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
17053 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
17054 * length. However, if delivery of a software interrupt, software exception or privileged
17055 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
17056 */
17057 VMXVEXITINFO ExitInfo;
17058 RT_ZERO(ExitInfo);
17059 ExitInfo.uReason = pVmxTransient->uExitReason;
17060 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17061 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17062
17063 VMXVEXITEVENTINFO ExitEventInfo;
17064 RT_ZERO(ExitEventInfo);
17065 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
17066 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
17067 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17068 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17069
17070#ifdef DEBUG_ramshankar
17071 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
17072 Log4Func(("cs:rip=%#04x:%#RX64 %s err_code=%#x exit_qual=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
17073 VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo) ? "#PF" : "Unk",
17074 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
17075 Log4Func(("idt_info=%#RX64 (%s) idt_errcode=%#RX32\n", pVmxTransient->uIdtVectoringInfo,
17076 VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo) ? "Valid" : "Invalid",
17077 pVmxTransient->uIdtVectoringErrorCode));
17078#endif
17079 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
17080 }
17081
17082 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
17083 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
17084 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
17085 }
17086
17087 /*
17088 * Software interrupts:
17089 * VM-exits cannot be caused by software interrupts.
17090 *
17091 * External interrupts:
17092 * This should only happen when "acknowledge external interrupts on VM-exit"
17093 * control is set. However, we never set this when executing a guest or
17094 * nested-guest. For nested-guests it is emulated while injecting interrupts into
17095 * the guest.
17096 */
17097 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
17098 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
17099 default:
17100 {
17101 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
17102 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
17103 }
17104 }
17105}
17106
17107
17108/**
17109 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
17110 * Unconditional VM-exit.
17111 */
17112HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17113{
17114 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17115 return IEMExecVmxVmexitTripleFault(pVCpu);
17116}
17117
17118
17119/**
17120 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
17121 */
17122HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17123{
17124 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17125
17126 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
17127 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17128 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17129}
17130
17131
17132/**
17133 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
17134 */
17135HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17136{
17137 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17138
17139 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
17140 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17141 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17142}
17143
17144
17145/**
17146 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
17147 * Unconditional VM-exit.
17148 */
17149HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17150{
17151 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17152
17153 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17154 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17155 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17156 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17157 AssertRCReturn(rc, rc);
17158
17159 VMXVEXITINFO ExitInfo;
17160 RT_ZERO(ExitInfo);
17161 ExitInfo.uReason = pVmxTransient->uExitReason;
17162 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17163 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17164
17165 VMXVEXITEVENTINFO ExitEventInfo;
17166 RT_ZERO(ExitEventInfo);
17167 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17168 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17169 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
17170}
17171
17172
17173/**
17174 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
17175 */
17176HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17177{
17178 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17179
17180 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
17181 {
17182 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17183 AssertRCReturn(rc, rc);
17184 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17185 }
17186 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
17187}
17188
17189
17190/**
17191 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
17192 */
17193HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17194{
17195 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17196
17197 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17198 {
17199 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17200 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17201 AssertRCReturn(rc, rc);
17202
17203 VMXVEXITINFO ExitInfo;
17204 RT_ZERO(ExitInfo);
17205 ExitInfo.uReason = pVmxTransient->uExitReason;
17206 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17207 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17208 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17209 }
17210 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17211}
17212
17213
17214/**
17215 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17216 */
17217HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17218{
17219 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17220
17221 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17222 {
17223 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17224 AssertRCReturn(rc, rc);
17225 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17226 }
17227 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17228}
17229
17230
17231/**
17232 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17233 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17234 */
17235HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17236{
17237 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17238
17239 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17240 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17241
17242 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17243 AssertRCReturn(rc, rc);
17244
17245 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17246 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17247 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17248
17249 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17250 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17251 u64VmcsField &= UINT64_C(0xffffffff);
17252
17253 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17254 {
17255 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17256 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17257 AssertRCReturn(rc, rc);
17258
17259 VMXVEXITINFO ExitInfo;
17260 RT_ZERO(ExitInfo);
17261 ExitInfo.uReason = pVmxTransient->uExitReason;
17262 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17263 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17264 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17265 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17266 }
17267
17268 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17269 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17270 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17271}
17272
17273
17274/**
17275 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17276 */
17277HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17278{
17279 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17280
17281 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17282 {
17283 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17284 AssertRCReturn(rc, rc);
17285 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17286 }
17287
17288 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17289}
17290
17291
17292/**
17293 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17294 * Conditional VM-exit.
17295 */
17296HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17297{
17298 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17299
17300 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17301 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17302 AssertRCReturn(rc, rc);
17303
17304 VBOXSTRICTRC rcStrict;
17305 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17306 switch (uAccessType)
17307 {
17308 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17309 {
17310 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17311 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17312 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17313 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17314
17315 bool fIntercept;
17316 switch (iCrReg)
17317 {
17318 case 0:
17319 case 4:
17320 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17321 break;
17322
17323 case 3:
17324 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17325 break;
17326
17327 case 8:
17328 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17329 break;
17330
17331 default:
17332 fIntercept = false;
17333 break;
17334 }
17335 if (fIntercept)
17336 {
17337 VMXVEXITINFO ExitInfo;
17338 RT_ZERO(ExitInfo);
17339 ExitInfo.uReason = pVmxTransient->uExitReason;
17340 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17341 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17342 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17343 }
17344 else
17345 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17346 break;
17347 }
17348
17349 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17350 {
17351 /*
17352 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17353 * CR2 reads do not cause a VM-exit.
17354 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17355 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17356 */
17357 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17358 if ( iCrReg == 3
17359 || iCrReg == 8)
17360 {
17361 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17362 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17363 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17364 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17365 {
17366 VMXVEXITINFO ExitInfo;
17367 RT_ZERO(ExitInfo);
17368 ExitInfo.uReason = pVmxTransient->uExitReason;
17369 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17370 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17371 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17372 }
17373 else
17374 {
17375 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17376 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17377 }
17378 }
17379 else
17380 {
17381 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17382 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17383 }
17384 break;
17385 }
17386
17387 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17388 {
17389 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17390 Assert(pVmcsNstGst);
17391 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17392 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17393 if ( (uGstHostMask & X86_CR0_TS)
17394 && (uReadShadow & X86_CR0_TS))
17395 {
17396 VMXVEXITINFO ExitInfo;
17397 RT_ZERO(ExitInfo);
17398 ExitInfo.uReason = pVmxTransient->uExitReason;
17399 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17400 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17401 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17402 }
17403 else
17404 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17405 break;
17406 }
17407
17408 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17409 {
17410 RTGCPTR GCPtrEffDst;
17411 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17412 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17413 if (fMemOperand)
17414 {
17415 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17416 AssertRCReturn(rc, rc);
17417 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17418 }
17419 else
17420 GCPtrEffDst = NIL_RTGCPTR;
17421
17422 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17423 {
17424 VMXVEXITINFO ExitInfo;
17425 RT_ZERO(ExitInfo);
17426 ExitInfo.uReason = pVmxTransient->uExitReason;
17427 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17428 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17429 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17430 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17431 }
17432 else
17433 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17434 break;
17435 }
17436
17437 default:
17438 {
17439 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17440 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17441 }
17442 }
17443
17444 if (rcStrict == VINF_IEM_RAISED_XCPT)
17445 {
17446 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17447 rcStrict = VINF_SUCCESS;
17448 }
17449 return rcStrict;
17450}
17451
17452
17453/**
17454 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17455 * Conditional VM-exit.
17456 */
17457HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17458{
17459 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17460
17461 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17462 {
17463 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17464 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17465 AssertRCReturn(rc, rc);
17466
17467 VMXVEXITINFO ExitInfo;
17468 RT_ZERO(ExitInfo);
17469 ExitInfo.uReason = pVmxTransient->uExitReason;
17470 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17471 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17472 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17473 }
17474 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17475}
17476
17477
17478/**
17479 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17480 * Conditional VM-exit.
17481 */
17482HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17483{
17484 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17485
17486 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17487 AssertRCReturn(rc, rc);
17488
17489 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17490 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17491 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17492
17493 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17494 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17495 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17496 {
17497 /*
17498 * IN/OUT instruction:
17499 * - Provides VM-exit instruction length.
17500 *
17501 * INS/OUTS instruction:
17502 * - Provides VM-exit instruction length.
17503 * - Provides Guest-linear address.
17504 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17505 */
17506 PVM pVM = pVCpu->CTX_SUFF(pVM);
17507 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17508 AssertRCReturn(rc, rc);
17509
17510 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17511 pVmxTransient->ExitInstrInfo.u = 0;
17512 pVmxTransient->uGuestLinearAddr = 0;
17513
17514 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17515 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17516 if (fIOString)
17517 {
17518 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17519 if (fVmxInsOutsInfo)
17520 {
17521 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17522 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17523 }
17524 }
17525 AssertRCReturn(rc, rc);
17526
17527 VMXVEXITINFO ExitInfo;
17528 RT_ZERO(ExitInfo);
17529 ExitInfo.uReason = pVmxTransient->uExitReason;
17530 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17531 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17532 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17533 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17534 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17535 }
17536 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17537}
17538
17539
17540/**
17541 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17542 */
17543HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17544{
17545 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17546
17547 uint32_t fMsrpm;
17548 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17549 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17550 else
17551 fMsrpm = VMXMSRPM_EXIT_RD;
17552
17553 if (fMsrpm & VMXMSRPM_EXIT_RD)
17554 {
17555 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17556 AssertRCReturn(rc, rc);
17557 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17558 }
17559 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17560}
17561
17562
17563/**
17564 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17565 */
17566HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17567{
17568 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17569
17570 uint32_t fMsrpm;
17571 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17572 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17573 else
17574 fMsrpm = VMXMSRPM_EXIT_WR;
17575
17576 if (fMsrpm & VMXMSRPM_EXIT_WR)
17577 {
17578 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17579 AssertRCReturn(rc, rc);
17580 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17581 }
17582 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17583}
17584
17585
17586/**
17587 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17588 */
17589HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17590{
17591 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17592
17593 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17594 {
17595 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17596 AssertRCReturn(rc, rc);
17597 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17598 }
17599 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17600}
17601
17602
17603/**
17604 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17605 * VM-exit.
17606 */
17607HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17608{
17609 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17610
17611 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17612 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17613}
17614
17615
17616/**
17617 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17618 */
17619HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17620{
17621 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17622
17623 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17624 {
17625 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17626 AssertRCReturn(rc, rc);
17627 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17628 }
17629 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17630}
17631
17632
17633/**
17634 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17635 */
17636HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17637{
17638 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17639
17640 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17641 * PAUSE when executing a nested-guest? If it does not, we would not need
17642 * to check for the intercepts here. Just call VM-exit... */
17643
17644 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17645 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17646 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17647 {
17648 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17649 AssertRCReturn(rc, rc);
17650 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17651 }
17652 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17653}
17654
17655
17656/**
17657 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17658 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17659 */
17660HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17661{
17662 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17663
17664 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17665 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17666 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17667}
17668
17669
17670/**
17671 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17672 * VM-exit.
17673 */
17674HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17675{
17676 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17677
17678 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17679 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17680 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17681 AssertRCReturn(rc, rc);
17682
17683 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17684 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17685 AssertRCReturn(rc, rc);
17686
17687 VMXVEXITINFO ExitInfo;
17688 RT_ZERO(ExitInfo);
17689 ExitInfo.uReason = pVmxTransient->uExitReason;
17690 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17691 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17692
17693 VMXVEXITEVENTINFO ExitEventInfo;
17694 RT_ZERO(ExitEventInfo);
17695 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17696 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17697 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17698}
17699
17700
17701/**
17702 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17703 * Conditional VM-exit.
17704 */
17705HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17706{
17707 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17708
17709 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17710 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17711 AssertRCReturn(rc, rc);
17712
17713 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17714}
17715
17716
17717/**
17718 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17719 * Conditional VM-exit.
17720 */
17721HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17722{
17723 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17724
17725 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17726 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17727 AssertRCReturn(rc, rc);
17728
17729 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17730}
17731
17732
17733/**
17734 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17735 */
17736HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17737{
17738 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17739
17740 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17741 {
17742 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17743 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17744 AssertRCReturn(rc, rc);
17745 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17746 }
17747 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17748}
17749
17750
17751/**
17752 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17753 */
17754HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17755{
17756 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17757
17758 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17759 {
17760 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17761 AssertRCReturn(rc, rc);
17762 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17763 }
17764 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17765}
17766
17767
17768/**
17769 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17770 */
17771HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17772{
17773 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17774
17775 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17776 {
17777 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17778 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17779 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17780 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17781 AssertRCReturn(rc, rc);
17782
17783 VMXVEXITINFO ExitInfo;
17784 RT_ZERO(ExitInfo);
17785 ExitInfo.uReason = pVmxTransient->uExitReason;
17786 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17787 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17788 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17789 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17790 }
17791 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17792}
17793
17794
17795/**
17796 * Nested-guest VM-exit handler for invalid-guest state
17797 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17798 */
17799HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17800{
17801 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17802
17803 /*
17804 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17805 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17806 * Handle it like it's in an invalid guest state of the outer guest.
17807 *
17808 * When the fast path is implemented, this should be changed to cause the corresponding
17809 * nested-guest VM-exit.
17810 */
17811 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17812}
17813
17814
17815/**
17816 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17817 * and only provide the instruction length.
17818 *
17819 * Unconditional VM-exit.
17820 */
17821HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17822{
17823 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17824
17825#ifdef VBOX_STRICT
17826 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17827 switch (pVmxTransient->uExitReason)
17828 {
17829 case VMX_EXIT_ENCLS:
17830 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17831 break;
17832
17833 case VMX_EXIT_VMFUNC:
17834 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17835 break;
17836 }
17837#endif
17838
17839 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17840 AssertRCReturn(rc, rc);
17841 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17842}
17843
17844
17845/**
17846 * Nested-guest VM-exit handler for instructions that provide instruction length as
17847 * well as more information.
17848 *
17849 * Unconditional VM-exit.
17850 */
17851HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17852{
17853 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17854
17855#ifdef VBOX_STRICT
17856 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17857 switch (pVmxTransient->uExitReason)
17858 {
17859 case VMX_EXIT_GDTR_IDTR_ACCESS:
17860 case VMX_EXIT_LDTR_TR_ACCESS:
17861 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17862 break;
17863
17864 case VMX_EXIT_RDRAND:
17865 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17866 break;
17867
17868 case VMX_EXIT_RDSEED:
17869 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17870 break;
17871
17872 case VMX_EXIT_XSAVES:
17873 case VMX_EXIT_XRSTORS:
17874 /** @todo NSTVMX: Verify XSS-bitmap. */
17875 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17876 break;
17877
17878 case VMX_EXIT_UMWAIT:
17879 case VMX_EXIT_TPAUSE:
17880 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17881 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17882 break;
17883 }
17884#endif
17885
17886 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17887 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17888 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17889 AssertRCReturn(rc, rc);
17890
17891 VMXVEXITINFO ExitInfo;
17892 RT_ZERO(ExitInfo);
17893 ExitInfo.uReason = pVmxTransient->uExitReason;
17894 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17895 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17896 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17897 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17898}
17899
17900/** @} */
17901#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17902
Note: See TracBrowser for help on using the repository browser.

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