VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Check VMX_EXIT_CTLS_ACK_EXT_INT before causing an external interrupt VM-exit (with interrupts still pending). Logging and assertion nits.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 731.0 KB
Line 
1/* $Id: HMVMXR0.cpp 79832 2019-07-17 11:26:01Z 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_FULL_GUEST_STATE
51# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
52# define HMVMX_ALWAYS_CLEAN_TRANSIENT
53# define HMVMX_ALWAYS_CHECK_GUEST_STATE
54# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
55# define HMVMX_ALWAYS_TRAP_PF
56# define HMVMX_ALWAYS_FLUSH_TLB
57# define HMVMX_ALWAYS_SWAP_EFER
58#endif
59
60
61/*********************************************************************************************************************************
62* Defined Constants And Macros *
63*********************************************************************************************************************************/
64/** Use the function table. */
65#define HMVMX_USE_FUNCTION_TABLE
66
67/** Determine which tagged-TLB flush handler to use. */
68#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
69#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
70#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
71#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
72
73/**
74 * Flags to skip redundant reads of some common VMCS fields that are not part of
75 * the guest-CPU or VCPU state but are needed while handling VM-exits.
76 */
77#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
78#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
79#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
80#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
81#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
82#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
83#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
84#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
85
86/** All the VMCS fields required for processing of exception/NMI VM-exits. */
87#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
88 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
89 | HMVMX_READ_EXIT_INSTR_LEN \
90 | HMVMX_READ_IDT_VECTORING_INFO \
91 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
92
93/** Assert that all the given fields have been read from the VMCS. */
94#ifdef VBOX_STRICT
95# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
96 do { \
97 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
98 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
99 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
100 } while (0)
101#else
102# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
103#endif
104
105/**
106 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
107 * guest using hardware-assisted VMX.
108 *
109 * This excludes state like GPRs (other than RSP) which are always are
110 * swapped and restored across the world-switch and also registers like EFER,
111 * MSR which cannot be modified by the guest without causing a VM-exit.
112 */
113#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
114 | CPUMCTX_EXTRN_RFLAGS \
115 | CPUMCTX_EXTRN_RSP \
116 | CPUMCTX_EXTRN_SREG_MASK \
117 | CPUMCTX_EXTRN_TABLE_MASK \
118 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
119 | CPUMCTX_EXTRN_SYSCALL_MSRS \
120 | CPUMCTX_EXTRN_SYSENTER_MSRS \
121 | CPUMCTX_EXTRN_TSC_AUX \
122 | CPUMCTX_EXTRN_OTHER_MSRS \
123 | CPUMCTX_EXTRN_CR0 \
124 | CPUMCTX_EXTRN_CR3 \
125 | CPUMCTX_EXTRN_CR4 \
126 | CPUMCTX_EXTRN_DR7 \
127 | CPUMCTX_EXTRN_HWVIRT \
128 | CPUMCTX_EXTRN_HM_VMX_MASK)
129
130/**
131 * Exception bitmap mask for real-mode guests (real-on-v86).
132 *
133 * We need to intercept all exceptions manually except:
134 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
135 * due to bugs in Intel CPUs.
136 * - \#PF need not be intercepted even in real-mode if we have nested paging
137 * support.
138 */
139#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
140 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
141 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
142 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
143 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
144 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
145 | RT_BIT(X86_XCPT_XF))
146
147/** Maximum VM-instruction error number. */
148#define HMVMX_INSTR_ERROR_MAX 28
149
150/** Profiling macro. */
151#ifdef HM_PROFILE_EXIT_DISPATCH
152# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
153# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
154#else
155# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
156# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
157#endif
158
159/** Assert that preemption is disabled or covered by thread-context hooks. */
160#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
161 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
162
163/** Assert that we haven't migrated CPUs when thread-context hooks are not
164 * used. */
165#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
166 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
167 ("Illegal migration! Entered on CPU %u Current %u\n", \
168 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
169
170/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
171 * context. */
172#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
173 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
174 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
175
176/** Log the VM-exit reason with an easily visible marker to identify it in a
177 * potential sea of logging data. */
178#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
179 do { \
180 const char * const pszExit = HMGetVmxExitName((a_uExitReason)); \
181 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, pszExit)); \
182 } while (0) \
183
184
185/*********************************************************************************************************************************
186* Structures and Typedefs *
187*********************************************************************************************************************************/
188/**
189 * VMX per-VCPU transient state.
190 *
191 * A state structure for holding miscellaneous information across
192 * VMX non-root operation and restored after the transition.
193 */
194typedef struct VMXTRANSIENT
195{
196 /** The host's rflags/eflags. */
197 RTCCUINTREG fEFlags;
198#if HC_ARCH_BITS == 32
199 uint32_t u32Alignment0;
200#endif
201 /** The guest's TPR value used for TPR shadowing. */
202 uint8_t u8GuestTpr;
203 /** Alignment. */
204 uint8_t abAlignment0[7];
205
206 /** The basic VM-exit reason. */
207 uint16_t uExitReason;
208 /** Alignment. */
209 uint16_t u16Alignment0;
210 /** The VM-exit interruption error code. */
211 uint32_t uExitIntErrorCode;
212 /** The VM-exit exit code qualification. */
213 uint64_t uExitQual;
214 /** The Guest-linear address. */
215 uint64_t uGuestLinearAddr;
216
217 /** The VM-exit interruption-information field. */
218 uint32_t uExitIntInfo;
219 /** The VM-exit instruction-length field. */
220 uint32_t cbInstr;
221 /** The VM-exit instruction-information field. */
222 VMXEXITINSTRINFO ExitInstrInfo;
223 /** Whether the VM-entry failed or not. */
224 bool fVMEntryFailed;
225 /** Whether we are currently executing a nested-guest. */
226 bool fIsNestedGuest;
227 /** Alignment. */
228 uint8_t abAlignment1[2];
229
230 /** The VM-entry interruption-information field. */
231 uint32_t uEntryIntInfo;
232 /** The VM-entry exception error code field. */
233 uint32_t uEntryXcptErrorCode;
234 /** The VM-entry instruction length field. */
235 uint32_t cbEntryInstr;
236
237 /** IDT-vectoring information field. */
238 uint32_t uIdtVectoringInfo;
239 /** IDT-vectoring error code. */
240 uint32_t uIdtVectoringErrorCode;
241
242 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
243 uint32_t fVmcsFieldsRead;
244
245 /** Whether the guest debug state was active at the time of VM-exit. */
246 bool fWasGuestDebugStateActive;
247 /** Whether the hyper debug state was active at the time of VM-exit. */
248 bool fWasHyperDebugStateActive;
249 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
250 bool fUpdatedTscOffsettingAndPreemptTimer;
251 /** Whether the VM-exit was caused by a page-fault during delivery of a
252 * contributory exception or a page-fault. */
253 bool fVectoringDoublePF;
254 /** Whether the VM-exit was caused by a page-fault during delivery of an
255 * external interrupt or NMI. */
256 bool fVectoringPF;
257 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
258 * area after VM-exit. */
259 bool fRemoveTscAuxMsr;
260 bool afAlignment0[2];
261
262 /** The VMCS info. object. */
263 PVMXVMCSINFO pVmcsInfo;
264} VMXTRANSIENT;
265AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
266AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
267AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
268AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
269AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
270AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
271/** Pointer to VMX transient state. */
272typedef VMXTRANSIENT *PVMXTRANSIENT;
273/** Pointer to a const VMX transient state. */
274typedef const VMXTRANSIENT *PCVMXTRANSIENT;
275
276/**
277 * Memory operand read or write access.
278 */
279typedef enum VMXMEMACCESS
280{
281 VMXMEMACCESS_READ = 0,
282 VMXMEMACCESS_WRITE = 1
283} VMXMEMACCESS;
284
285/**
286 * VMX VM-exit handler.
287 *
288 * @returns Strict VBox status code (i.e. informational status codes too).
289 * @param pVCpu The cross context virtual CPU structure.
290 * @param pVmxTransient The VMX-transient structure.
291 */
292#ifndef HMVMX_USE_FUNCTION_TABLE
293typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
294#else
295typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
296/** Pointer to VM-exit handler. */
297typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
298#endif
299
300/**
301 * VMX VM-exit handler, non-strict status code.
302 *
303 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
304 *
305 * @returns VBox status code, no informational status code returned.
306 * @param pVCpu The cross context virtual CPU structure.
307 * @param pVmxTransient The VMX-transient structure.
308 *
309 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
310 * use of that status code will be replaced with VINF_EM_SOMETHING
311 * later when switching over to IEM.
312 */
313#ifndef HMVMX_USE_FUNCTION_TABLE
314typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
315#else
316typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
317#endif
318
319
320/*********************************************************************************************************************************
321* Internal Functions *
322*********************************************************************************************************************************/
323#ifndef HMVMX_USE_FUNCTION_TABLE
324DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
325# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
326# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
327#else
328# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
329# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
330#endif
331#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
332DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
333#endif
334
335static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
336#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
337static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
338#endif
339
340/** @name VM-exit handler prototypes.
341 * @{
342 */
343static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
344static FNVMXEXITHANDLER hmR0VmxExitExtInt;
345static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
346static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
347static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
348static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
349static FNVMXEXITHANDLER hmR0VmxExitCpuid;
350static FNVMXEXITHANDLER hmR0VmxExitGetsec;
351static FNVMXEXITHANDLER hmR0VmxExitHlt;
352static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
353static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
354static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
355static FNVMXEXITHANDLER hmR0VmxExitVmcall;
356#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
357static FNVMXEXITHANDLER hmR0VmxExitVmclear;
358static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
359static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
360static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
361static FNVMXEXITHANDLER hmR0VmxExitVmread;
362static FNVMXEXITHANDLER hmR0VmxExitVmresume;
363static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
364static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
365static FNVMXEXITHANDLER hmR0VmxExitVmxon;
366static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
367#endif
368static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
369static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
370static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
371static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
372static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
373static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
374static FNVMXEXITHANDLER hmR0VmxExitMwait;
375static FNVMXEXITHANDLER hmR0VmxExitMtf;
376static FNVMXEXITHANDLER hmR0VmxExitMonitor;
377static FNVMXEXITHANDLER hmR0VmxExitPause;
378static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
379static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
380static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
381static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
382static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
383static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
384static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
385static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
386static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
387static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
389static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
390/** @} */
391
392#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
393/** @name Nested-guest VM-exit handler prototypes.
394 * @{
395 */
396static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
397static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
398static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
399static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
400static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
401static FNVMXEXITHANDLER hmR0VmxExitHltNested;
402static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
403static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
404static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
405static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
406static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
407static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
408static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
409static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
410static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
411static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
412static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
413static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
414static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
415static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
416static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
417static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
418static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
419static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
420static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
421static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
422static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
423static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
424static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
425/** @} */
426#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
427
428
429/*********************************************************************************************************************************
430* Global Variables *
431*********************************************************************************************************************************/
432#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
433/**
434 * Array of all VMCS fields.
435 * Any fields added to the VT-x spec. should be added here.
436 *
437 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
438 * of nested-guests.
439 */
440static const uint32_t g_aVmcsFields[] =
441{
442 /* 16-bit control fields. */
443 VMX_VMCS16_VPID,
444 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
445 VMX_VMCS16_EPTP_INDEX,
446
447 /* 16-bit guest-state fields. */
448 VMX_VMCS16_GUEST_ES_SEL,
449 VMX_VMCS16_GUEST_CS_SEL,
450 VMX_VMCS16_GUEST_SS_SEL,
451 VMX_VMCS16_GUEST_DS_SEL,
452 VMX_VMCS16_GUEST_FS_SEL,
453 VMX_VMCS16_GUEST_GS_SEL,
454 VMX_VMCS16_GUEST_LDTR_SEL,
455 VMX_VMCS16_GUEST_TR_SEL,
456 VMX_VMCS16_GUEST_INTR_STATUS,
457 VMX_VMCS16_GUEST_PML_INDEX,
458
459 /* 16-bits host-state fields. */
460 VMX_VMCS16_HOST_ES_SEL,
461 VMX_VMCS16_HOST_CS_SEL,
462 VMX_VMCS16_HOST_SS_SEL,
463 VMX_VMCS16_HOST_DS_SEL,
464 VMX_VMCS16_HOST_FS_SEL,
465 VMX_VMCS16_HOST_GS_SEL,
466 VMX_VMCS16_HOST_TR_SEL,
467
468 /* 64-bit control fields. */
469 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
470 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
471 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
472 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
473 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
474 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
475 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
476 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
477 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
478 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
479 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
480 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
481 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
482 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
483 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
484 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
485 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
486 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
487 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
488 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
489 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
490 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
491 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
492 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
493 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
494 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
495 VMX_VMCS64_CTRL_EPTP_FULL,
496 VMX_VMCS64_CTRL_EPTP_HIGH,
497 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
498 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
499 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
500 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
501 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
502 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
503 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
504 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
505 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
506 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
507 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
508 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
509 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
510 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
511 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
512 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
513 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
514 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
515 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
516 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
517 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
518 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
519
520 /* 64-bit read-only data fields. */
521 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
522 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
523
524 /* 64-bit guest-state fields. */
525 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
526 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
527 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
528 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
529 VMX_VMCS64_GUEST_PAT_FULL,
530 VMX_VMCS64_GUEST_PAT_HIGH,
531 VMX_VMCS64_GUEST_EFER_FULL,
532 VMX_VMCS64_GUEST_EFER_HIGH,
533 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
534 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
535 VMX_VMCS64_GUEST_PDPTE0_FULL,
536 VMX_VMCS64_GUEST_PDPTE0_HIGH,
537 VMX_VMCS64_GUEST_PDPTE1_FULL,
538 VMX_VMCS64_GUEST_PDPTE1_HIGH,
539 VMX_VMCS64_GUEST_PDPTE2_FULL,
540 VMX_VMCS64_GUEST_PDPTE2_HIGH,
541 VMX_VMCS64_GUEST_PDPTE3_FULL,
542 VMX_VMCS64_GUEST_PDPTE3_HIGH,
543 VMX_VMCS64_GUEST_BNDCFGS_FULL,
544 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
545
546 /* 64-bit host-state fields. */
547 VMX_VMCS64_HOST_PAT_FULL,
548 VMX_VMCS64_HOST_PAT_HIGH,
549 VMX_VMCS64_HOST_EFER_FULL,
550 VMX_VMCS64_HOST_EFER_HIGH,
551 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
552 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
553
554 /* 32-bit control fields. */
555 VMX_VMCS32_CTRL_PIN_EXEC,
556 VMX_VMCS32_CTRL_PROC_EXEC,
557 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
558 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
559 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
560 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
561 VMX_VMCS32_CTRL_EXIT,
562 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
563 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
564 VMX_VMCS32_CTRL_ENTRY,
565 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
566 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
567 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
568 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
569 VMX_VMCS32_CTRL_TPR_THRESHOLD,
570 VMX_VMCS32_CTRL_PROC_EXEC2,
571 VMX_VMCS32_CTRL_PLE_GAP,
572 VMX_VMCS32_CTRL_PLE_WINDOW,
573
574 /* 32-bits read-only fields. */
575 VMX_VMCS32_RO_VM_INSTR_ERROR,
576 VMX_VMCS32_RO_EXIT_REASON,
577 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
578 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
579 VMX_VMCS32_RO_IDT_VECTORING_INFO,
580 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
581 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
582 VMX_VMCS32_RO_EXIT_INSTR_INFO,
583
584 /* 32-bit guest-state fields. */
585 VMX_VMCS32_GUEST_ES_LIMIT,
586 VMX_VMCS32_GUEST_CS_LIMIT,
587 VMX_VMCS32_GUEST_SS_LIMIT,
588 VMX_VMCS32_GUEST_DS_LIMIT,
589 VMX_VMCS32_GUEST_FS_LIMIT,
590 VMX_VMCS32_GUEST_GS_LIMIT,
591 VMX_VMCS32_GUEST_LDTR_LIMIT,
592 VMX_VMCS32_GUEST_TR_LIMIT,
593 VMX_VMCS32_GUEST_GDTR_LIMIT,
594 VMX_VMCS32_GUEST_IDTR_LIMIT,
595 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
596 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
597 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
598 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
599 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
602 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
603 VMX_VMCS32_GUEST_INT_STATE,
604 VMX_VMCS32_GUEST_ACTIVITY_STATE,
605 VMX_VMCS32_GUEST_SMBASE,
606 VMX_VMCS32_GUEST_SYSENTER_CS,
607 VMX_VMCS32_PREEMPT_TIMER_VALUE,
608
609 /* 32-bit host-state fields. */
610 VMX_VMCS32_HOST_SYSENTER_CS,
611
612 /* Natural-width control fields. */
613 VMX_VMCS_CTRL_CR0_MASK,
614 VMX_VMCS_CTRL_CR4_MASK,
615 VMX_VMCS_CTRL_CR0_READ_SHADOW,
616 VMX_VMCS_CTRL_CR4_READ_SHADOW,
617 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
618 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
619 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
620 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
621
622 /* Natural-width read-only data fields. */
623 VMX_VMCS_RO_EXIT_QUALIFICATION,
624 VMX_VMCS_RO_IO_RCX,
625 VMX_VMCS_RO_IO_RSI,
626 VMX_VMCS_RO_IO_RDI,
627 VMX_VMCS_RO_IO_RIP,
628 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
629
630 /* Natural-width guest-state field */
631 VMX_VMCS_GUEST_CR0,
632 VMX_VMCS_GUEST_CR3,
633 VMX_VMCS_GUEST_CR4,
634 VMX_VMCS_GUEST_ES_BASE,
635 VMX_VMCS_GUEST_CS_BASE,
636 VMX_VMCS_GUEST_SS_BASE,
637 VMX_VMCS_GUEST_DS_BASE,
638 VMX_VMCS_GUEST_FS_BASE,
639 VMX_VMCS_GUEST_GS_BASE,
640 VMX_VMCS_GUEST_LDTR_BASE,
641 VMX_VMCS_GUEST_TR_BASE,
642 VMX_VMCS_GUEST_GDTR_BASE,
643 VMX_VMCS_GUEST_IDTR_BASE,
644 VMX_VMCS_GUEST_DR7,
645 VMX_VMCS_GUEST_RSP,
646 VMX_VMCS_GUEST_RIP,
647 VMX_VMCS_GUEST_RFLAGS,
648 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
649 VMX_VMCS_GUEST_SYSENTER_ESP,
650 VMX_VMCS_GUEST_SYSENTER_EIP,
651
652 /* Natural-width host-state fields */
653 VMX_VMCS_HOST_CR0,
654 VMX_VMCS_HOST_CR3,
655 VMX_VMCS_HOST_CR4,
656 VMX_VMCS_HOST_FS_BASE,
657 VMX_VMCS_HOST_GS_BASE,
658 VMX_VMCS_HOST_TR_BASE,
659 VMX_VMCS_HOST_GDTR_BASE,
660 VMX_VMCS_HOST_IDTR_BASE,
661 VMX_VMCS_HOST_SYSENTER_ESP,
662 VMX_VMCS_HOST_SYSENTER_EIP,
663 VMX_VMCS_HOST_RSP,
664 VMX_VMCS_HOST_RIP
665};
666#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
667
668#ifdef VMX_USE_CACHED_VMCS_ACCESSES
669static const uint32_t g_aVmcsCacheSegBase[] =
670{
671 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
672 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
673 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
674 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
675 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
676 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
677};
678AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
679#endif
680static const uint32_t g_aVmcsSegBase[] =
681{
682 VMX_VMCS_GUEST_ES_BASE,
683 VMX_VMCS_GUEST_CS_BASE,
684 VMX_VMCS_GUEST_SS_BASE,
685 VMX_VMCS_GUEST_DS_BASE,
686 VMX_VMCS_GUEST_FS_BASE,
687 VMX_VMCS_GUEST_GS_BASE
688};
689static const uint32_t g_aVmcsSegSel[] =
690{
691 VMX_VMCS16_GUEST_ES_SEL,
692 VMX_VMCS16_GUEST_CS_SEL,
693 VMX_VMCS16_GUEST_SS_SEL,
694 VMX_VMCS16_GUEST_DS_SEL,
695 VMX_VMCS16_GUEST_FS_SEL,
696 VMX_VMCS16_GUEST_GS_SEL
697};
698static const uint32_t g_aVmcsSegLimit[] =
699{
700 VMX_VMCS32_GUEST_ES_LIMIT,
701 VMX_VMCS32_GUEST_CS_LIMIT,
702 VMX_VMCS32_GUEST_SS_LIMIT,
703 VMX_VMCS32_GUEST_DS_LIMIT,
704 VMX_VMCS32_GUEST_FS_LIMIT,
705 VMX_VMCS32_GUEST_GS_LIMIT
706};
707static const uint32_t g_aVmcsSegAttr[] =
708{
709 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
710 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
711 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
712 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
713 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
714 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
715};
716AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
717AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
718AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
719AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
720
721#ifdef HMVMX_USE_FUNCTION_TABLE
722/**
723 * VMX_EXIT dispatch table.
724 */
725static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
726{
727 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
728 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
729 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
730 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
731 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
732 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
733 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
734 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
735 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
736 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
737 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
738 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
739 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
740 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
741 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
742 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
743 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
744 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
745 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
746#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
747 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
748 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
749 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
750 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
751 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
752 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
753 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
754 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
755 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
756#else
757 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
758 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
759 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
760 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
761 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
762 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
763 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
764 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
765 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
766#endif
767 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
768 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
769 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
770 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
771 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
772 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
773 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
774 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
775 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
776 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
777 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
778 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
779 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
780 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
781 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
782 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
783 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
784 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
785 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
786 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
787 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
788 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
789 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
790 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
791 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
792#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
793 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
794#else
795 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
796#endif
797 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
798 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
799 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
800 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
801 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
802 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
803 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
804 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
805 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
806 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
807 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
808 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
809 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
810 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
811 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
812};
813#endif /* HMVMX_USE_FUNCTION_TABLE */
814
815#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
816static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
817{
818 /* 0 */ "(Not Used)",
819 /* 1 */ "VMCALL executed in VMX root operation.",
820 /* 2 */ "VMCLEAR with invalid physical address.",
821 /* 3 */ "VMCLEAR with VMXON pointer.",
822 /* 4 */ "VMLAUNCH with non-clear VMCS.",
823 /* 5 */ "VMRESUME with non-launched VMCS.",
824 /* 6 */ "VMRESUME after VMXOFF",
825 /* 7 */ "VM-entry with invalid control fields.",
826 /* 8 */ "VM-entry with invalid host state fields.",
827 /* 9 */ "VMPTRLD with invalid physical address.",
828 /* 10 */ "VMPTRLD with VMXON pointer.",
829 /* 11 */ "VMPTRLD with incorrect revision identifier.",
830 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
831 /* 13 */ "VMWRITE to read-only VMCS component.",
832 /* 14 */ "(Not Used)",
833 /* 15 */ "VMXON executed in VMX root operation.",
834 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
835 /* 17 */ "VM-entry with non-launched executing VMCS.",
836 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
837 /* 19 */ "VMCALL with non-clear VMCS.",
838 /* 20 */ "VMCALL with invalid VM-exit control fields.",
839 /* 21 */ "(Not Used)",
840 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
841 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
842 /* 24 */ "VMCALL with invalid SMM-monitor features.",
843 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
844 /* 26 */ "VM-entry with events blocked by MOV SS.",
845 /* 27 */ "(Not Used)",
846 /* 28 */ "Invalid operand to INVEPT/INVVPID."
847};
848#endif /* VBOX_STRICT && LOG_ENABLED */
849
850
851/**
852 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
853 *
854 * Any bit set in this mask is owned by the host/hypervisor and would cause a
855 * VM-exit when modified by the guest.
856 *
857 * @returns The static CR0 guest/host mask.
858 * @param pVCpu The cross context virtual CPU structure.
859 */
860DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
861{
862 /*
863 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
864 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
865 */
866 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
867 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
868 * and @bugref{6944}. */
869 PVM pVM = pVCpu->CTX_SUFF(pVM);
870 return ( X86_CR0_PE
871 | X86_CR0_NE
872 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
873 | X86_CR0_PG
874 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
875 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
876 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
877}
878
879
880/**
881 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
882 *
883 * Any bit set in this mask is owned by the host/hypervisor and would cause a
884 * VM-exit when modified by the guest.
885 *
886 * @returns The static CR4 guest/host mask.
887 * @param pVCpu The cross context virtual CPU structure.
888 */
889DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
890{
891 /*
892 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
893 * these bits are reserved on hardware that does not support them. Since the
894 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
895 * these bits and handle it depending on whether we expose them to the guest.
896 */
897 PVM pVM = pVCpu->CTX_SUFF(pVM);
898 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
899 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
900 return ( X86_CR4_VMXE
901 | X86_CR4_VME
902 | X86_CR4_PAE
903 | X86_CR4_PGE
904 | X86_CR4_PSE
905 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
906 | (fPcid ? X86_CR4_PCIDE : 0));
907}
908
909
910/**
911 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
912 * area.
913 *
914 * @returns @c true if it's different, @c false otherwise.
915 * @param pVmcsInfo The VMCS info. object.
916 */
917DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
918{
919 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
920 && pVmcsInfo->pvGuestMsrStore);
921}
922
923
924/**
925 * Sets the given Processor-based VM-execution controls.
926 *
927 * @param pVmxTransient The VMX-transient structure.
928 * @param uProcCtls The Processor-based VM-execution controls to set.
929 */
930static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
931{
932 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
933 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
934 {
935 pVmcsInfo->u32ProcCtls |= uProcCtls;
936 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
937 AssertRC(rc);
938 }
939}
940
941
942/**
943 * Removes the given Processor-based VM-execution controls.
944 *
945 * @param pVCpu The cross context virtual CPU structure.
946 * @param pVmxTransient The VMX-transient structure.
947 * @param uProcCtls The Processor-based VM-execution controls to remove.
948 *
949 * @remarks When executing a nested-guest, this will not remove any of the specified
950 * controls if the guest hypervisor has set any one of them.
951 */
952static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
953{
954 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
955 if (pVmcsInfo->u32ProcCtls & uProcCtls)
956 {
957#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
958 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
959 ? true
960 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
961#else
962 NOREF(pVCpu);
963 bool const fRemoveCtls = true;
964#endif
965 if (fRemoveCtls)
966 {
967 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
968 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
969 AssertRC(rc);
970 }
971 }
972}
973
974
975/**
976 * Sets the TSC offset for the current VMCS.
977 *
978 * @param pVCpu The cross context virtual CPU structure.
979 * @param uTscOffset The TSC offset to set.
980 * @param pVmcsInfo The VMCS info. object.
981 */
982static void hmR0VmxSetTscOffsetVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
983{
984 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
985 if (pVmcsInfo->u64TscOffset != uTscOffset)
986 {
987 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
988 AssertRC(rc);
989 pVmcsInfo->u64TscOffset = uTscOffset;
990 }
991}
992
993
994/**
995 * Adds one or more exceptions to the exception bitmap and commits it to the current
996 * VMCS.
997 *
998 * @returns VBox status code.
999 * @param pVmxTransient The VMX-transient structure.
1000 * @param uXcptMask The exception(s) to add.
1001 */
1002static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1003{
1004 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1005 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1006 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1007 {
1008 uXcptBitmap |= uXcptMask;
1009 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1010 AssertRCReturn(rc, rc);
1011 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1012 }
1013 return VINF_SUCCESS;
1014}
1015
1016
1017/**
1018 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1019 *
1020 * @returns VBox status code.
1021 * @param pVmxTransient The VMX-transient structure.
1022 * @param uXcpt The exception to add.
1023 */
1024static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1025{
1026 Assert(uXcpt <= X86_XCPT_LAST);
1027 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1028}
1029
1030
1031/**
1032 * Remove one or more exceptions from the exception bitmap and commits it to the
1033 * current VMCS.
1034 *
1035 * This takes care of not removing the exception intercept if a nested-guest
1036 * requires the exception to be intercepted.
1037 *
1038 * @returns VBox status code.
1039 * @param pVCpu The cross context virtual CPU structure.
1040 * @param pVmxTransient The VMX-transient structure.
1041 * @param uXcptMask The exception(s) to remove.
1042 */
1043static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1044{
1045 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1046 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1047 if (u32XcptBitmap & uXcptMask)
1048 {
1049#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1050 if (!pVmxTransient->fIsNestedGuest)
1051 { /* likely */ }
1052 else
1053 {
1054 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1055 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1056 }
1057#endif
1058#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1059 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1060 | RT_BIT(X86_XCPT_DE)
1061 | RT_BIT(X86_XCPT_NM)
1062 | RT_BIT(X86_XCPT_TS)
1063 | RT_BIT(X86_XCPT_UD)
1064 | RT_BIT(X86_XCPT_NP)
1065 | RT_BIT(X86_XCPT_SS)
1066 | RT_BIT(X86_XCPT_GP)
1067 | RT_BIT(X86_XCPT_PF)
1068 | RT_BIT(X86_XCPT_MF));
1069#elif defined(HMVMX_ALWAYS_TRAP_PF)
1070 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1071#endif
1072 if (uXcptMask)
1073 {
1074 /* Validate we are not removing any essential exception intercepts. */
1075 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
1076 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1077 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1078
1079 /* Remove it from the exception bitmap. */
1080 u32XcptBitmap &= ~uXcptMask;
1081
1082 /* Commit and update the cache if necessary. */
1083 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1084 {
1085 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1086 AssertRCReturn(rc, rc);
1087 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1088 }
1089 }
1090 }
1091 return VINF_SUCCESS;
1092}
1093
1094
1095/**
1096 * Remove an exceptions from the exception bitmap and commits it to the current
1097 * VMCS.
1098 *
1099 * @returns VBox status code.
1100 * @param pVCpu The cross context virtual CPU structure.
1101 * @param pVmxTransient The VMX-transient structure.
1102 * @param uXcpt The exception to remove.
1103 */
1104static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1105{
1106 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1107}
1108
1109
1110/**
1111 * Loads the VMCS specified by the VMCS info. object.
1112 *
1113 * @returns VBox status code.
1114 * @param pVmcsInfo The VMCS info. object.
1115 *
1116 * @remarks Can be called with interrupts disabled.
1117 */
1118static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1119{
1120 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1121 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1122
1123 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1124 if (RT_SUCCESS(rc))
1125 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1126 return rc;
1127}
1128
1129
1130/**
1131 * Clears the VMCS specified by the VMCS info. object.
1132 *
1133 * @returns VBox status code.
1134 * @param pVmcsInfo The VMCS info. object.
1135 *
1136 * @remarks Can be called with interrupts disabled.
1137 */
1138static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1139{
1140 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1141 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1142
1143 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1144 if (RT_SUCCESS(rc))
1145 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1146 return rc;
1147}
1148
1149
1150#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1151/**
1152 * Loads the shadow VMCS specified by the VMCS info. object.
1153 *
1154 * @returns VBox status code.
1155 * @param pVmcsInfo The VMCS info. object.
1156 *
1157 * @remarks Can be called with interrupts disabled.
1158 */
1159static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1160{
1161 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1162 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1163
1164 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1165 if (RT_SUCCESS(rc))
1166 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1167 return rc;
1168}
1169
1170
1171/**
1172 * Clears the shadow VMCS specified by the VMCS info. object.
1173 *
1174 * @returns VBox status code.
1175 * @param pVmcsInfo The VMCS info. object.
1176 *
1177 * @remarks Can be called with interrupts disabled.
1178 */
1179static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1180{
1181 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1182 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1183
1184 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1185 if (RT_SUCCESS(rc))
1186 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1187 return rc;
1188}
1189
1190
1191/**
1192 * Switches from and to the specified VMCSes.
1193 *
1194 * @returns VBox status code.
1195 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1196 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1197 *
1198 * @remarks Called with interrupts disabled.
1199 */
1200static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1201{
1202 /*
1203 * Clear the VMCS we are switching out if it has not already been cleared.
1204 * This will sync any CPU internal data back to the VMCS.
1205 */
1206 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1207 {
1208 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1209 if (RT_SUCCESS(rc))
1210 {
1211 /*
1212 * The shadow VMCS, if any, would not be active at this point since we
1213 * would have cleared it while importing the virtual hardware-virtualization
1214 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1215 * clear the shadow VMCS here, just assert for safety.
1216 */
1217 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1218 }
1219 else
1220 return rc;
1221 }
1222
1223 /*
1224 * Clear the VMCS we are switching to if it has not already been cleared.
1225 * This will initialize the VMCS launch state to "clear" required for loading it.
1226 *
1227 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1228 */
1229 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1230 {
1231 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1232 if (RT_SUCCESS(rc))
1233 { /* likely */ }
1234 else
1235 return rc;
1236 }
1237
1238 /*
1239 * Finally, load the VMCS we are switching to.
1240 */
1241 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1242}
1243
1244
1245/**
1246 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1247 * caller.
1248 *
1249 * @returns VBox status code.
1250 * @param pVCpu The cross context virtual CPU structure.
1251 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1252 * true) or guest VMCS (pass false).
1253 */
1254static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1255{
1256 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1257 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1258
1259 PVMXVMCSINFO pVmcsInfoFrom;
1260 PVMXVMCSINFO pVmcsInfoTo;
1261 if (fSwitchToNstGstVmcs)
1262 {
1263 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1264 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1265 }
1266 else
1267 {
1268 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1269 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1270 }
1271
1272 /*
1273 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1274 * preemption hook code path acquires the current VMCS.
1275 */
1276 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1277
1278 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1279 if (RT_SUCCESS(rc))
1280 {
1281 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1282
1283 /*
1284 * If we are switching to a VMCS that was executed on a different host CPU or was
1285 * never executed before, flag that we need to export the host state before executing
1286 * guest/nested-guest code using hardware-assisted VMX.
1287 *
1288 * This could probably be done in a preemptible context since the preemption hook
1289 * will flag the necessary change in host context. However, since preemption is
1290 * already disabled and to avoid making assumptions about host specific code in
1291 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1292 * disabled.
1293 */
1294 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1295 { /* likely */ }
1296 else
1297 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1298
1299 ASMSetFlags(fEFlags);
1300
1301 /*
1302 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1303 * flag that we need to update the host MSR values there. Even if we decide in the
1304 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1305 * if its content differs, we would have to update the host MSRs anyway.
1306 */
1307 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1308 }
1309 else
1310 ASMSetFlags(fEFlags);
1311 return rc;
1312}
1313#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1314
1315
1316/**
1317 * Updates the VM's last error record.
1318 *
1319 * If there was a VMX instruction error, reads the error data from the VMCS and
1320 * updates VCPU's last error record as well.
1321 *
1322 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1323 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1324 * VERR_VMX_INVALID_VMCS_FIELD.
1325 * @param rc The error code.
1326 */
1327static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1328{
1329 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1330 || rc == VERR_VMX_UNABLE_TO_START_VM)
1331 {
1332 AssertPtrReturnVoid(pVCpu);
1333 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1334 }
1335 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1336}
1337
1338
1339#ifdef VBOX_STRICT
1340/**
1341 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1342 * transient structure.
1343 *
1344 * @returns VBox status code.
1345 * @param pVmxTransient The VMX-transient structure.
1346 *
1347 * @remarks No-long-jump zone!!!
1348 */
1349DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1350{
1351 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1352 AssertRCReturn(rc, rc);
1353 return VINF_SUCCESS;
1354}
1355
1356
1357/**
1358 * Reads the VM-entry exception error code field from the VMCS into
1359 * the VMX transient structure.
1360 *
1361 * @returns VBox status code.
1362 * @param pVmxTransient The VMX-transient structure.
1363 *
1364 * @remarks No-long-jump zone!!!
1365 */
1366DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1367{
1368 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1369 AssertRCReturn(rc, rc);
1370 return VINF_SUCCESS;
1371}
1372
1373
1374/**
1375 * Reads the VM-entry exception error code field from the VMCS into
1376 * the VMX transient structure.
1377 *
1378 * @returns VBox status code.
1379 * @param pVmxTransient The VMX-transient structure.
1380 *
1381 * @remarks No-long-jump zone!!!
1382 */
1383DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1384{
1385 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1386 AssertRCReturn(rc, rc);
1387 return VINF_SUCCESS;
1388}
1389#endif /* VBOX_STRICT */
1390
1391
1392/**
1393 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1394 * transient structure.
1395 *
1396 * @returns VBox status code.
1397 * @param pVmxTransient The VMX-transient structure.
1398 */
1399DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1400{
1401 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1402 {
1403 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1404 AssertRCReturn(rc,rc);
1405 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1406 }
1407 return VINF_SUCCESS;
1408}
1409
1410
1411/**
1412 * Reads the VM-exit interruption error code from the VMCS into the VMX
1413 * transient structure.
1414 *
1415 * @returns VBox status code.
1416 * @param pVmxTransient The VMX-transient structure.
1417 */
1418DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1419{
1420 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1421 {
1422 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1423 AssertRCReturn(rc, rc);
1424 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1425 }
1426 return VINF_SUCCESS;
1427}
1428
1429
1430/**
1431 * Reads the VM-exit instruction length field from the VMCS into the VMX
1432 * transient structure.
1433 *
1434 * @returns VBox status code.
1435 * @param pVmxTransient The VMX-transient structure.
1436 */
1437DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1438{
1439 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1440 {
1441 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1442 AssertRCReturn(rc, rc);
1443 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1444 }
1445 return VINF_SUCCESS;
1446}
1447
1448
1449/**
1450 * Reads the VM-exit instruction-information field from the VMCS into
1451 * the VMX transient structure.
1452 *
1453 * @returns VBox status code.
1454 * @param pVmxTransient The VMX-transient structure.
1455 */
1456DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1457{
1458 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1459 {
1460 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1461 AssertRCReturn(rc, rc);
1462 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1463 }
1464 return VINF_SUCCESS;
1465}
1466
1467
1468/**
1469 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1470 *
1471 * @returns VBox status code.
1472 * @param pVCpu The cross context virtual CPU structure of the
1473 * calling EMT. (Required for the VMCS cache case.)
1474 * @param pVmxTransient The VMX-transient structure.
1475 */
1476DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1477{
1478 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1479 {
1480 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1481 AssertRCReturn(rc, rc);
1482 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1483 }
1484 return VINF_SUCCESS;
1485}
1486
1487
1488/**
1489 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1490 *
1491 * @returns VBox status code.
1492 * @param pVCpu The cross context virtual CPU structure of the
1493 * calling EMT. (Required for the VMCS cache case.)
1494 * @param pVmxTransient The VMX-transient structure.
1495 */
1496DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1497{
1498 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1499 {
1500 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1501 AssertRCReturn(rc, rc);
1502 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1503 }
1504 return VINF_SUCCESS;
1505}
1506
1507
1508/**
1509 * Reads the IDT-vectoring information field from the VMCS into the VMX
1510 * transient structure.
1511 *
1512 * @returns VBox status code.
1513 * @param pVmxTransient The VMX-transient structure.
1514 *
1515 * @remarks No-long-jump zone!!!
1516 */
1517DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1518{
1519 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1520 {
1521 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1522 AssertRCReturn(rc, rc);
1523 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1524 }
1525 return VINF_SUCCESS;
1526}
1527
1528
1529/**
1530 * Reads the IDT-vectoring error code from the VMCS into the VMX
1531 * transient structure.
1532 *
1533 * @returns VBox status code.
1534 * @param pVmxTransient The VMX-transient structure.
1535 */
1536DECLINLINE(int) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1537{
1538 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1539 {
1540 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1541 AssertRCReturn(rc, rc);
1542 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1543 }
1544 return VINF_SUCCESS;
1545}
1546
1547
1548/**
1549 * Enters VMX root mode operation on the current CPU.
1550 *
1551 * @returns VBox status code.
1552 * @param pVM The cross context VM structure. Can be
1553 * NULL, after a resume.
1554 * @param HCPhysCpuPage Physical address of the VMXON region.
1555 * @param pvCpuPage Pointer to the VMXON region.
1556 */
1557static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1558{
1559 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1560 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1561 Assert(pvCpuPage);
1562 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1563
1564 if (pVM)
1565 {
1566 /* Write the VMCS revision identifier to the VMXON region. */
1567 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1568 }
1569
1570 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1571 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1572
1573 /* Enable the VMX bit in CR4 if necessary. */
1574 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1575
1576 /* Enter VMX root mode. */
1577 int rc = VMXEnable(HCPhysCpuPage);
1578 if (RT_FAILURE(rc))
1579 {
1580 if (!(uOldCr4 & X86_CR4_VMXE))
1581 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1582
1583 if (pVM)
1584 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1585 }
1586
1587 /* Restore interrupts. */
1588 ASMSetFlags(fEFlags);
1589 return rc;
1590}
1591
1592
1593/**
1594 * Exits VMX root mode operation on the current CPU.
1595 *
1596 * @returns VBox status code.
1597 */
1598static int hmR0VmxLeaveRootMode(void)
1599{
1600 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1601
1602 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1603 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1604
1605 /* If we're for some reason not in VMX root mode, then don't leave it. */
1606 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1607
1608 int rc;
1609 if (uHostCr4 & X86_CR4_VMXE)
1610 {
1611 /* Exit VMX root mode and clear the VMX bit in CR4. */
1612 VMXDisable();
1613 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1614 rc = VINF_SUCCESS;
1615 }
1616 else
1617 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1618
1619 /* Restore interrupts. */
1620 ASMSetFlags(fEFlags);
1621 return rc;
1622}
1623
1624
1625/**
1626 * Allocates and maps a physically contiguous page. The allocated page is
1627 * zero'd out (used by various VT-x structures).
1628 *
1629 * @returns IPRT status code.
1630 * @param pMemObj Pointer to the ring-0 memory object.
1631 * @param ppVirt Where to store the virtual address of the allocation.
1632 * @param pHCPhys Where to store the physical address of the allocation.
1633 */
1634static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1635{
1636 AssertPtr(pMemObj);
1637 AssertPtr(ppVirt);
1638 AssertPtr(pHCPhys);
1639 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1640 if (RT_FAILURE(rc))
1641 return rc;
1642 *ppVirt = RTR0MemObjAddress(*pMemObj);
1643 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1644 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1645 return VINF_SUCCESS;
1646}
1647
1648
1649/**
1650 * Frees and unmaps an allocated, physical page.
1651 *
1652 * @param pMemObj Pointer to the ring-0 memory object.
1653 * @param ppVirt Where to re-initialize the virtual address of allocation as
1654 * 0.
1655 * @param pHCPhys Where to re-initialize the physical address of the
1656 * allocation as 0.
1657 */
1658static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1659{
1660 AssertPtr(pMemObj);
1661 AssertPtr(ppVirt);
1662 AssertPtr(pHCPhys);
1663 /* NULL is valid, accepted and ignored by the free function below. */
1664 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1665 *pMemObj = NIL_RTR0MEMOBJ;
1666 *ppVirt = NULL;
1667 *pHCPhys = NIL_RTHCPHYS;
1668}
1669
1670
1671/**
1672 * Initializes a VMCS info. object.
1673 *
1674 * @param pVmcsInfo The VMCS info. object.
1675 */
1676static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1677{
1678 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1679
1680 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1681 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1682 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1683 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1684 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1685 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1686 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1687 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1688 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1689 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1690 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1691 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1692 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1693 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1694 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1695 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1696}
1697
1698
1699/**
1700 * Frees the VT-x structures for a VMCS info. object.
1701 *
1702 * @param pVM The cross context VM structure.
1703 * @param pVmcsInfo The VMCS info. object.
1704 */
1705static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1706{
1707 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1708
1709#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1710 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1711 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1712#endif
1713
1714 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1715 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1716
1717 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1718 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1719 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1720
1721 hmR0VmxInitVmcsInfo(pVmcsInfo);
1722}
1723
1724
1725/**
1726 * Allocates the VT-x structures for a VMCS info. object.
1727 *
1728 * @returns VBox status code.
1729 * @param pVCpu The cross context virtual CPU structure.
1730 * @param pVmcsInfo The VMCS info. object.
1731 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1732 */
1733static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1734{
1735 PVM pVM = pVCpu->CTX_SUFF(pVM);
1736
1737 /* Allocate the guest VM control structure (VMCS). */
1738 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1739 if (RT_SUCCESS(rc))
1740 {
1741 if (!fIsNstGstVmcs)
1742 {
1743#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1744 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1745 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1746#endif
1747 if (RT_SUCCESS(rc))
1748 {
1749 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1750 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1751 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1752 {
1753 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1754 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1755 }
1756 }
1757 }
1758 else
1759 {
1760 /* We don't yet support exposing VMCS shadowing to the guest. */
1761 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1762 Assert(!pVmcsInfo->pvShadowVmcs);
1763
1764 /* Get the allocated virtual-APIC page from CPUM. */
1765 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1766 {
1767 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1768 &pVmcsInfo->HCPhysVirtApic);
1769 Assert(pVmcsInfo->pbVirtApic);
1770 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1771 }
1772 }
1773
1774 if (RT_SUCCESS(rc))
1775 {
1776 /*
1777 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1778 * transparent accesses of specific MSRs.
1779 *
1780 * If the condition for enabling MSR bitmaps changes here, don't forget to
1781 * update HMIsMsrBitmapActive().
1782 *
1783 * We don't share MSR bitmaps between the guest and nested-guest as we then
1784 * don't need to care about carefully restoring the guest MSR bitmap.
1785 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1786 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1787 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1788 * we do that later while merging VMCS.
1789 */
1790 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1791 {
1792 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1793 if ( RT_SUCCESS(rc)
1794 && !fIsNstGstVmcs)
1795 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1796 }
1797
1798 if (RT_SUCCESS(rc))
1799 {
1800 /*
1801 * Allocate the VM-entry MSR-load area for the guest MSRs.
1802 *
1803 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1804 * the guest and nested-guest.
1805 */
1806 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1807 &pVmcsInfo->HCPhysGuestMsrLoad);
1808 if (RT_SUCCESS(rc))
1809 {
1810 /*
1811 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1812 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1813 */
1814 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1815 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1816 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1817
1818 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1819 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1820 &pVmcsInfo->HCPhysHostMsrLoad);
1821 }
1822 }
1823 }
1824 }
1825
1826 return rc;
1827}
1828
1829
1830/**
1831 * Free all VT-x structures for the VM.
1832 *
1833 * @returns IPRT status code.
1834 * @param pVM The cross context VM structure.
1835 */
1836static void hmR0VmxStructsFree(PVM pVM)
1837{
1838#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1839 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1840#endif
1841 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1842
1843#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1844 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1845 {
1846 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1847 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1848 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1849 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1850 }
1851#endif
1852
1853 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1854 {
1855 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1856 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1857 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1858#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1859 if (pVM->cpum.ro.GuestFeatures.fVmx)
1860 {
1861 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1862 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1863 }
1864#endif
1865 }
1866}
1867
1868
1869/**
1870 * Allocate all VT-x structures for the VM.
1871 *
1872 * @returns IPRT status code.
1873 * @param pVM The cross context VM structure.
1874 */
1875static int hmR0VmxStructsAlloc(PVM pVM)
1876{
1877 /*
1878 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1879 * The VMCS size cannot be more than 4096 bytes.
1880 *
1881 * See Intel spec. Appendix A.1 "Basic VMX Information".
1882 */
1883 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1884 if (cbVmcs <= X86_PAGE_4K_SIZE)
1885 { /* likely */ }
1886 else
1887 {
1888 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1889 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1890 }
1891
1892 /*
1893 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1894 */
1895#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1896 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1897 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1898 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1899#endif
1900
1901 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1902 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1903 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1904
1905 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1906 {
1907 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1908 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1909 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1910 }
1911
1912 /*
1913 * Allocate per-VM VT-x structures.
1914 */
1915 int rc = VINF_SUCCESS;
1916#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1917 /* Allocate crash-dump magic scratch page. */
1918 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1919 if (RT_FAILURE(rc))
1920 {
1921 hmR0VmxStructsFree(pVM);
1922 return rc;
1923 }
1924 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1925 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1926#endif
1927
1928 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1929 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1930 {
1931 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1932 &pVM->hm.s.vmx.HCPhysApicAccess);
1933 if (RT_FAILURE(rc))
1934 {
1935 hmR0VmxStructsFree(pVM);
1936 return rc;
1937 }
1938 }
1939
1940#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1941 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1942 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1943 {
1944 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1945 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1946 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1947 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1948 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1949 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1950 {
1951 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1952 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1953 if (RT_SUCCESS(rc))
1954 {
1955 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1956 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1957 }
1958 }
1959 else
1960 rc = VERR_NO_MEMORY;
1961
1962 if (RT_FAILURE(rc))
1963 {
1964 hmR0VmxStructsFree(pVM);
1965 return rc;
1966 }
1967 }
1968#endif
1969
1970 /*
1971 * Initialize per-VCPU VT-x structures.
1972 */
1973 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1974 {
1975 /* Allocate the guest VMCS structures. */
1976 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1977 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1978 if (RT_SUCCESS(rc))
1979 {
1980#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1981 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1982 if (pVM->cpum.ro.GuestFeatures.fVmx)
1983 {
1984 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1985 if (RT_SUCCESS(rc))
1986 { /* likely */ }
1987 else
1988 break;
1989 }
1990#endif
1991 }
1992 else
1993 break;
1994 }
1995
1996 if (RT_FAILURE(rc))
1997 {
1998 hmR0VmxStructsFree(pVM);
1999 return rc;
2000 }
2001
2002 return VINF_SUCCESS;
2003}
2004
2005#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2006/**
2007 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2008 *
2009 * @returns @c true if the MSR is intercepted, @c false otherwise.
2010 * @param pvMsrBitmap The MSR bitmap.
2011 * @param offMsr The MSR byte offset.
2012 * @param iBit The bit offset from the byte offset.
2013 */
2014DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2015{
2016 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2017 Assert(pbMsrBitmap);
2018 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2019 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2020}
2021#endif
2022
2023/**
2024 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2025 *
2026 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2027 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2028 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2029 * the read/write access of this MSR.
2030 *
2031 * @param pVCpu The cross context virtual CPU structure.
2032 * @param pVmcsInfo The VMCS info. object.
2033 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2034 * @param idMsr The MSR value.
2035 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2036 * include both a read -and- a write permission!
2037 *
2038 * @sa CPUMGetVmxMsrPermission.
2039 * @remarks Can be called with interrupts disabled.
2040 */
2041static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2042{
2043 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2044 Assert(pbMsrBitmap);
2045 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2046
2047 /*
2048 * MSR-bitmap Layout:
2049 * Byte index MSR range Interpreted as
2050 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2051 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2052 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2053 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2054 *
2055 * A bit corresponding to an MSR within the above range causes a VM-exit
2056 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2057 * the MSR range, it always cause a VM-exit.
2058 *
2059 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2060 */
2061 uint16_t const offBitmapRead = 0;
2062 uint16_t const offBitmapWrite = 0x800;
2063 uint16_t offMsr;
2064 int32_t iBit;
2065 if (idMsr <= UINT32_C(0x00001fff))
2066 {
2067 offMsr = 0;
2068 iBit = idMsr;
2069 }
2070 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2071 {
2072 offMsr = 0x400;
2073 iBit = idMsr - UINT32_C(0xc0000000);
2074 }
2075 else
2076 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2077
2078 /*
2079 * Set the MSR read permission.
2080 */
2081 uint16_t const offMsrRead = offBitmapRead + offMsr;
2082 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2083 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2084 {
2085#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2086 bool const fClear = !fIsNstGstVmcs ? true
2087 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2088#else
2089 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2090 bool const fClear = true;
2091#endif
2092 if (fClear)
2093 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2094 }
2095 else
2096 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2097
2098 /*
2099 * Set the MSR write permission.
2100 */
2101 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2102 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2103 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2104 {
2105#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2106 bool const fClear = !fIsNstGstVmcs ? true
2107 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2108#else
2109 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2110 bool const fClear = true;
2111#endif
2112 if (fClear)
2113 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2114 }
2115 else
2116 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2117}
2118
2119
2120/**
2121 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2122 * area.
2123 *
2124 * @returns VBox status code.
2125 * @param pVCpu The cross context virtual CPU structure.
2126 * @param pVmcsInfo The VMCS info. object.
2127 * @param cMsrs The number of MSRs.
2128 */
2129static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2130{
2131 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2132 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2133 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2134 {
2135 /* Commit the MSR counts to the VMCS and update the cache. */
2136 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2137 {
2138 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
2139 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
2140 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
2141 AssertRCReturn(rc, rc);
2142
2143 pVmcsInfo->cEntryMsrLoad = cMsrs;
2144 pVmcsInfo->cExitMsrStore = cMsrs;
2145 pVmcsInfo->cExitMsrLoad = cMsrs;
2146 }
2147 return VINF_SUCCESS;
2148 }
2149
2150 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2151 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2152 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2153}
2154
2155
2156/**
2157 * Adds a new (or updates the value of an existing) guest/host MSR
2158 * pair to be swapped during the world-switch as part of the
2159 * auto-load/store MSR area in the VMCS.
2160 *
2161 * @returns VBox status code.
2162 * @param pVCpu The cross context virtual CPU structure.
2163 * @param pVmxTransient The VMX-transient structure.
2164 * @param idMsr The MSR.
2165 * @param uGuestMsrValue Value of the guest MSR.
2166 * @param fSetReadWrite Whether to set the guest read/write access of this
2167 * MSR (thus not causing a VM-exit).
2168 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2169 * necessary.
2170 */
2171static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2172 bool fSetReadWrite, bool fUpdateHostMsr)
2173{
2174 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2175 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2176 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2177 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2178 uint32_t i;
2179
2180 /* Paranoia. */
2181 Assert(pGuestMsrLoad);
2182
2183 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2184
2185 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2186 for (i = 0; i < cMsrs; i++)
2187 {
2188 if (pGuestMsrLoad[i].u32Msr == idMsr)
2189 break;
2190 }
2191
2192 bool fAdded = false;
2193 if (i == cMsrs)
2194 {
2195 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2196 ++cMsrs;
2197 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2198 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2199
2200 /* Set the guest to read/write this MSR without causing VM-exits. */
2201 if ( fSetReadWrite
2202 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2203 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2204
2205 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2206 fAdded = true;
2207 }
2208
2209 /* Update the MSR value for the newly added or already existing MSR. */
2210 pGuestMsrLoad[i].u32Msr = idMsr;
2211 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2212
2213 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2214 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2215 {
2216 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2217 pGuestMsrStore[i].u32Msr = idMsr;
2218 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2219 }
2220
2221 /* Update the corresponding slot in the host MSR area. */
2222 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2223 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2224 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2225 pHostMsr[i].u32Msr = idMsr;
2226
2227 /*
2228 * Only if the caller requests to update the host MSR value AND we've newly added the
2229 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2230 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2231 *
2232 * We do this for performance reasons since reading MSRs may be quite expensive.
2233 */
2234 if (fAdded)
2235 {
2236 if (fUpdateHostMsr)
2237 {
2238 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2239 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2240 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2241 }
2242 else
2243 {
2244 /* Someone else can do the work. */
2245 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2246 }
2247 }
2248 return VINF_SUCCESS;
2249}
2250
2251
2252/**
2253 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2254 * auto-load/store MSR area in the VMCS.
2255 *
2256 * @returns VBox status code.
2257 * @param pVCpu The cross context virtual CPU structure.
2258 * @param pVmxTransient The VMX-transient structure.
2259 * @param idMsr The MSR.
2260 */
2261static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2262{
2263 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2264 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2265 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2266 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2267
2268 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2269
2270 for (uint32_t i = 0; i < cMsrs; i++)
2271 {
2272 /* Find the MSR. */
2273 if (pGuestMsrLoad[i].u32Msr == idMsr)
2274 {
2275 /*
2276 * If it's the last MSR, we only need to reduce the MSR count.
2277 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2278 */
2279 if (i < cMsrs - 1)
2280 {
2281 /* Remove it from the VM-entry MSR-load area. */
2282 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2283 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2284
2285 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2286 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2287 {
2288 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2289 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2290 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2291 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2292 }
2293
2294 /* Remove it from the VM-exit MSR-load area. */
2295 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2296 Assert(pHostMsr[i].u32Msr == idMsr);
2297 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2298 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2299 }
2300
2301 /* Reduce the count to reflect the removed MSR and bail. */
2302 --cMsrs;
2303 break;
2304 }
2305 }
2306
2307 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2308 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2309 {
2310 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2311 AssertRCReturn(rc, rc);
2312
2313 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2314 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2315 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2316
2317 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2318 return VINF_SUCCESS;
2319 }
2320
2321 return VERR_NOT_FOUND;
2322}
2323
2324
2325/**
2326 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2327 *
2328 * @returns @c true if found, @c false otherwise.
2329 * @param pVmcsInfo The VMCS info. object.
2330 * @param idMsr The MSR to find.
2331 */
2332static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2333{
2334 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2335 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2336 Assert(pMsrs);
2337 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2338 for (uint32_t i = 0; i < cMsrs; i++)
2339 {
2340 if (pMsrs[i].u32Msr == idMsr)
2341 return true;
2342 }
2343 return false;
2344}
2345
2346
2347/**
2348 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2349 *
2350 * @param pVCpu The cross context virtual CPU structure.
2351 * @param pVmcsInfo The VMCS info. object.
2352 *
2353 * @remarks No-long-jump zone!!!
2354 */
2355static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2356{
2357 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2358
2359 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2360 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2361 Assert(pHostMsrLoad);
2362 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2363 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2364 for (uint32_t i = 0; i < cMsrs; i++)
2365 {
2366 /*
2367 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2368 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2369 */
2370 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2371 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2372 else
2373 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2374 }
2375}
2376
2377
2378/**
2379 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2380 * perform lazy restoration of the host MSRs while leaving VT-x.
2381 *
2382 * @param pVCpu The cross context virtual CPU structure.
2383 *
2384 * @remarks No-long-jump zone!!!
2385 */
2386static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2387{
2388 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2389
2390 /*
2391 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2392 */
2393 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2394 {
2395 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2396#if HC_ARCH_BITS == 64
2397 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2398 {
2399 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2400 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2401 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2402 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2403 }
2404#endif
2405 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2406 }
2407}
2408
2409
2410/**
2411 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2412 * lazily while leaving VT-x.
2413 *
2414 * @returns true if it does, false otherwise.
2415 * @param pVCpu The cross context virtual CPU structure.
2416 * @param idMsr The MSR to check.
2417 */
2418static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2419{
2420 NOREF(pVCpu);
2421#if HC_ARCH_BITS == 64
2422 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2423 {
2424 switch (idMsr)
2425 {
2426 case MSR_K8_LSTAR:
2427 case MSR_K6_STAR:
2428 case MSR_K8_SF_MASK:
2429 case MSR_K8_KERNEL_GS_BASE:
2430 return true;
2431 }
2432 }
2433#else
2434 RT_NOREF(pVCpu, idMsr);
2435#endif
2436 return false;
2437}
2438
2439
2440/**
2441 * Loads a set of guests MSRs to allow read/passthru to the guest.
2442 *
2443 * The name of this function is slightly confusing. This function does NOT
2444 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2445 * common prefix for functions dealing with "lazy restoration" of the shared
2446 * MSRs.
2447 *
2448 * @param pVCpu The cross context virtual CPU structure.
2449 *
2450 * @remarks No-long-jump zone!!!
2451 */
2452static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2453{
2454 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2455 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2456
2457 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2458#if HC_ARCH_BITS == 64
2459 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2460 {
2461 /*
2462 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2463 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2464 * we can skip a few MSR writes.
2465 *
2466 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2467 * guest MSR values in the guest-CPU context might be different to what's currently
2468 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2469 * CPU, see @bugref{8728}.
2470 */
2471 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2472 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2473 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2474 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2475 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2476 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2477 {
2478#ifdef VBOX_STRICT
2479 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2480 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2481 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2482 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2483#endif
2484 }
2485 else
2486 {
2487 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2488 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2489 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2490 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2491 }
2492 }
2493#endif
2494 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2495}
2496
2497
2498/**
2499 * Performs lazy restoration of the set of host MSRs if they were previously
2500 * loaded with guest MSR values.
2501 *
2502 * @param pVCpu The cross context virtual CPU structure.
2503 *
2504 * @remarks No-long-jump zone!!!
2505 * @remarks The guest MSRs should have been saved back into the guest-CPU
2506 * context by hmR0VmxImportGuestState()!!!
2507 */
2508static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2509{
2510 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2511 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2512
2513 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2514 {
2515 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2516#if HC_ARCH_BITS == 64
2517 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2518 {
2519 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2520 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2521 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2522 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2523 }
2524#endif
2525 }
2526 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2527}
2528
2529
2530/**
2531 * Verifies that our cached values of the VMCS fields are all consistent with
2532 * what's actually present in the VMCS.
2533 *
2534 * @returns VBox status code.
2535 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2536 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2537 * VMCS content. HMCPU error-field is
2538 * updated, see VMX_VCI_XXX.
2539 * @param pVCpu The cross context virtual CPU structure.
2540 * @param pVmcsInfo The VMCS info. object.
2541 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2542 */
2543static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2544{
2545 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2546
2547 uint32_t u32Val;
2548 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2549 AssertRCReturn(rc, rc);
2550 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2551 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2552 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2553 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2554
2555 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2556 AssertRCReturn(rc, rc);
2557 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2558 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2559 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2560 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2561
2562 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2563 AssertRCReturn(rc, rc);
2564 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2565 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2566 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2567 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2568
2569 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2570 AssertRCReturn(rc, rc);
2571 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2572 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2573 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2574 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2575
2576 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2577 {
2578 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2579 AssertRCReturn(rc, rc);
2580 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2581 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2582 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2583 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2584 }
2585
2586 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2587 AssertRCReturn(rc, rc);
2588 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2589 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2590 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2591 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2592
2593 uint64_t u64Val;
2594 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2595 AssertRCReturn(rc, rc);
2596 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2597 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2598 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2599 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2600
2601 NOREF(pcszVmcs);
2602 return VINF_SUCCESS;
2603}
2604
2605
2606#ifdef VBOX_STRICT
2607/**
2608 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2609 *
2610 * @param pVCpu The cross context virtual CPU structure.
2611 * @param pVmcsInfo The VMCS info. object.
2612 */
2613static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2614{
2615 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2616
2617 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2618 {
2619 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2620 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2621 uint64_t uVmcsEferMsrVmcs;
2622 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2623 AssertRC(rc);
2624
2625 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2626 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2627 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2628 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2629 }
2630}
2631
2632
2633/**
2634 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2635 * VMCS are correct.
2636 *
2637 * @param pVCpu The cross context virtual CPU structure.
2638 * @param pVmcsInfo The VMCS info. object.
2639 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2640 */
2641static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2642{
2643 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2644
2645 /* Read the various MSR-area counts from the VMCS. */
2646 uint32_t cEntryLoadMsrs;
2647 uint32_t cExitStoreMsrs;
2648 uint32_t cExitLoadMsrs;
2649 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2650 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2651 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2652
2653 /* Verify all the MSR counts are the same. */
2654 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2655 Assert(cExitStoreMsrs == cExitLoadMsrs);
2656 uint32_t const cMsrs = cExitLoadMsrs;
2657
2658 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2659 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2660
2661 /* Verify the MSR counts are within the allocated page size. */
2662 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2663
2664 /* Verify the relevant contents of the MSR areas match. */
2665 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2666 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2667 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2668 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2669 for (uint32_t i = 0; i < cMsrs; i++)
2670 {
2671 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2672 if (fSeparateExitMsrStorePage)
2673 {
2674 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2675 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2676 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2677 }
2678
2679 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2680 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2681 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2682
2683 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2684 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2685 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2686 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2687
2688 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2689 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2690 if (fIsEferMsr)
2691 {
2692 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2693 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2694 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2695 }
2696
2697 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2698 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2699 {
2700 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2701 if (fIsEferMsr)
2702 {
2703 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2704 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2705 }
2706 else
2707 {
2708 if (!fIsNstGstVmcs)
2709 {
2710 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2711 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2712 }
2713 else
2714 {
2715 /*
2716 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2717 * execute a nested-guest with MSR passthrough.
2718 *
2719 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2720 * allow passthrough too.
2721 */
2722 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2723 Assert(pvMsrBitmapNstGst);
2724 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2725 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2726 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2727 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2728 }
2729 }
2730 }
2731
2732 /* Move to the next MSR. */
2733 pHostMsrLoad++;
2734 pGuestMsrLoad++;
2735 pGuestMsrStore++;
2736 }
2737}
2738#endif /* VBOX_STRICT */
2739
2740
2741/**
2742 * Flushes the TLB using EPT.
2743 *
2744 * @returns VBox status code.
2745 * @param pVCpu The cross context virtual CPU structure of the calling
2746 * EMT. Can be NULL depending on @a enmTlbFlush.
2747 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2748 * enmTlbFlush.
2749 * @param enmTlbFlush Type of flush.
2750 *
2751 * @remarks Caller is responsible for making sure this function is called only
2752 * when NestedPaging is supported and providing @a enmTlbFlush that is
2753 * supported by the CPU.
2754 * @remarks Can be called with interrupts disabled.
2755 */
2756static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2757{
2758 uint64_t au64Descriptor[2];
2759 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2760 au64Descriptor[0] = 0;
2761 else
2762 {
2763 Assert(pVCpu);
2764 Assert(pVmcsInfo);
2765 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2766 }
2767 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2768
2769 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2770 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2771
2772 if ( RT_SUCCESS(rc)
2773 && pVCpu)
2774 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2775}
2776
2777
2778/**
2779 * Flushes the TLB using VPID.
2780 *
2781 * @returns VBox status code.
2782 * @param pVCpu The cross context virtual CPU structure of the calling
2783 * EMT. Can be NULL depending on @a enmTlbFlush.
2784 * @param enmTlbFlush Type of flush.
2785 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2786 * on @a enmTlbFlush).
2787 *
2788 * @remarks Can be called with interrupts disabled.
2789 */
2790static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2791{
2792 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2793
2794 uint64_t au64Descriptor[2];
2795 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2796 {
2797 au64Descriptor[0] = 0;
2798 au64Descriptor[1] = 0;
2799 }
2800 else
2801 {
2802 AssertPtr(pVCpu);
2803 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2804 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2805 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2806 au64Descriptor[1] = GCPtr;
2807 }
2808
2809 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2810 AssertMsg(rc == VINF_SUCCESS,
2811 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2812
2813 if ( RT_SUCCESS(rc)
2814 && pVCpu)
2815 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2816 NOREF(rc);
2817}
2818
2819
2820/**
2821 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2822 * otherwise there is nothing really to invalidate.
2823 *
2824 * @returns VBox status code.
2825 * @param pVCpu The cross context virtual CPU structure.
2826 * @param GCVirt Guest virtual address of the page to invalidate.
2827 */
2828VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2829{
2830 AssertPtr(pVCpu);
2831 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2832
2833 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2834 {
2835 /*
2836 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2837 * the EPT case. See @bugref{6043} and @bugref{6177}.
2838 *
2839 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2840 * as this function maybe called in a loop with individual addresses.
2841 */
2842 PVM pVM = pVCpu->CTX_SUFF(pVM);
2843 if (pVM->hm.s.vmx.fVpid)
2844 {
2845 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2846
2847#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2848 /*
2849 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2850 * where executing INVVPID outside 64-bit mode does not flush translations of
2851 * 64-bit linear addresses, see @bugref{6208#c72}.
2852 */
2853 if (RT_HI_U32(GCVirt))
2854 fVpidFlush = false;
2855#endif
2856
2857 if (fVpidFlush)
2858 {
2859 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2860 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2861 }
2862 else
2863 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2864 }
2865 else if (pVM->hm.s.fNestedPaging)
2866 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2867 }
2868
2869 return VINF_SUCCESS;
2870}
2871
2872
2873/**
2874 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2875 * case where neither EPT nor VPID is supported by the CPU.
2876 *
2877 * @param pHostCpu The HM physical-CPU structure.
2878 * @param pVCpu The cross context virtual CPU structure.
2879 *
2880 * @remarks Called with interrupts disabled.
2881 */
2882static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2883{
2884 AssertPtr(pVCpu);
2885 AssertPtr(pHostCpu);
2886
2887 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2888
2889 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2890 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2891 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2892 pVCpu->hm.s.fForceTLBFlush = false;
2893 return;
2894}
2895
2896
2897/**
2898 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2899 *
2900 * @param pHostCpu The HM physical-CPU structure.
2901 * @param pVCpu The cross context virtual CPU structure.
2902 * @param pVmcsInfo The VMCS info. object.
2903 *
2904 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2905 * nomenclature. The reason is, to avoid confusion in compare statements
2906 * since the host-CPU copies are named "ASID".
2907 *
2908 * @remarks Called with interrupts disabled.
2909 */
2910static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2911{
2912#ifdef VBOX_WITH_STATISTICS
2913 bool fTlbFlushed = false;
2914# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2915# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2916 if (!fTlbFlushed) \
2917 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2918 } while (0)
2919#else
2920# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2921# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2922#endif
2923
2924 AssertPtr(pVCpu);
2925 AssertPtr(pHostCpu);
2926 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2927
2928 PVM pVM = pVCpu->CTX_SUFF(pVM);
2929 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2930 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2931 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2932
2933 /*
2934 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2935 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2936 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2937 * cannot reuse the current ASID anymore.
2938 */
2939 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2940 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2941 {
2942 ++pHostCpu->uCurrentAsid;
2943 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2944 {
2945 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2946 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2947 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2948 }
2949
2950 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2951 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2952 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2953
2954 /*
2955 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2956 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2957 */
2958 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2959 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2960 HMVMX_SET_TAGGED_TLB_FLUSHED();
2961 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2962 }
2963 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2964 {
2965 /*
2966 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2967 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2968 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2969 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2970 * mappings, see @bugref{6568}.
2971 *
2972 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2973 */
2974 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2975 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2976 HMVMX_SET_TAGGED_TLB_FLUSHED();
2977 }
2978
2979 pVCpu->hm.s.fForceTLBFlush = false;
2980 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2981
2982 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2983 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2984 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2985 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2986 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2987 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2988 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2989 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2990 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2991
2992 /* Update VMCS with the VPID. */
2993 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2994 AssertRC(rc);
2995
2996#undef HMVMX_SET_TAGGED_TLB_FLUSHED
2997}
2998
2999
3000/**
3001 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3002 *
3003 * @param pHostCpu The HM physical-CPU structure.
3004 * @param pVCpu The cross context virtual CPU structure.
3005 * @param pVmcsInfo The VMCS info. object.
3006 *
3007 * @remarks Called with interrupts disabled.
3008 */
3009static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3010{
3011 AssertPtr(pVCpu);
3012 AssertPtr(pHostCpu);
3013 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3014 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3015 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3016
3017 /*
3018 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3019 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3020 */
3021 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3022 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3023 {
3024 pVCpu->hm.s.fForceTLBFlush = true;
3025 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3026 }
3027
3028 /* Check for explicit TLB flushes. */
3029 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3030 {
3031 pVCpu->hm.s.fForceTLBFlush = true;
3032 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3033 }
3034
3035 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3036 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3037
3038 if (pVCpu->hm.s.fForceTLBFlush)
3039 {
3040 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3041 pVCpu->hm.s.fForceTLBFlush = false;
3042 }
3043}
3044
3045
3046/**
3047 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3048 *
3049 * @param pHostCpu The HM physical-CPU structure.
3050 * @param pVCpu The cross context virtual CPU structure.
3051 *
3052 * @remarks Called with interrupts disabled.
3053 */
3054static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3055{
3056 AssertPtr(pVCpu);
3057 AssertPtr(pHostCpu);
3058 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3059 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3060 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3061
3062 /*
3063 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3064 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3065 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3066 * cannot reuse the current ASID anymore.
3067 */
3068 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3069 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3070 {
3071 pVCpu->hm.s.fForceTLBFlush = true;
3072 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3073 }
3074
3075 /* Check for explicit TLB flushes. */
3076 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3077 {
3078 /*
3079 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3080 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3081 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3082 * include fExplicitFlush's too) - an obscure corner case.
3083 */
3084 pVCpu->hm.s.fForceTLBFlush = true;
3085 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3086 }
3087
3088 PVM pVM = pVCpu->CTX_SUFF(pVM);
3089 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3090 if (pVCpu->hm.s.fForceTLBFlush)
3091 {
3092 ++pHostCpu->uCurrentAsid;
3093 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3094 {
3095 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3096 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3097 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3098 }
3099
3100 pVCpu->hm.s.fForceTLBFlush = false;
3101 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3102 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3103 if (pHostCpu->fFlushAsidBeforeUse)
3104 {
3105 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3106 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3107 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3108 {
3109 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3110 pHostCpu->fFlushAsidBeforeUse = false;
3111 }
3112 else
3113 {
3114 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3115 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3116 }
3117 }
3118 }
3119
3120 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3121 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3122 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3123 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3124 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3125 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3126 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3127
3128 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3129 AssertRC(rc);
3130}
3131
3132
3133/**
3134 * Flushes the guest TLB entry based on CPU capabilities.
3135 *
3136 * @param pHostCpu The HM physical-CPU structure.
3137 * @param pVCpu The cross context virtual CPU structure.
3138 * @param pVmcsInfo The VMCS info. object.
3139 *
3140 * @remarks Called with interrupts disabled.
3141 */
3142static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3143{
3144#ifdef HMVMX_ALWAYS_FLUSH_TLB
3145 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3146#endif
3147 PVM pVM = pVCpu->CTX_SUFF(pVM);
3148 switch (pVM->hm.s.vmx.enmTlbFlushType)
3149 {
3150 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3151 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3152 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3153 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3154 default:
3155 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3156 break;
3157 }
3158 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3159}
3160
3161
3162/**
3163 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3164 * TLB entries from the host TLB before VM-entry.
3165 *
3166 * @returns VBox status code.
3167 * @param pVM The cross context VM structure.
3168 */
3169static int hmR0VmxSetupTaggedTlb(PVM pVM)
3170{
3171 /*
3172 * Determine optimal flush type for nested paging.
3173 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3174 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3175 */
3176 if (pVM->hm.s.fNestedPaging)
3177 {
3178 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3179 {
3180 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3181 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3182 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3183 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3184 else
3185 {
3186 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3187 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3188 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3189 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3190 }
3191
3192 /* Make sure the write-back cacheable memory type for EPT is supported. */
3193 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3194 {
3195 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3196 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3197 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3198 }
3199
3200 /* EPT requires a page-walk length of 4. */
3201 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3202 {
3203 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3204 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3205 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3206 }
3207 }
3208 else
3209 {
3210 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3211 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3212 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3213 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3214 }
3215 }
3216
3217 /*
3218 * Determine optimal flush type for VPID.
3219 */
3220 if (pVM->hm.s.vmx.fVpid)
3221 {
3222 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3223 {
3224 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3225 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3226 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3227 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3228 else
3229 {
3230 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3231 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3232 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3233 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3234 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3235 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3236 pVM->hm.s.vmx.fVpid = false;
3237 }
3238 }
3239 else
3240 {
3241 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3242 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3243 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3244 pVM->hm.s.vmx.fVpid = false;
3245 }
3246 }
3247
3248 /*
3249 * Setup the handler for flushing tagged-TLBs.
3250 */
3251 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3252 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3253 else if (pVM->hm.s.fNestedPaging)
3254 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3255 else if (pVM->hm.s.vmx.fVpid)
3256 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3257 else
3258 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3259 return VINF_SUCCESS;
3260}
3261
3262
3263#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3264/**
3265 * Sets up the shadow VMCS fields arrays.
3266 *
3267 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3268 * executing the guest.
3269 *
3270 * @returns VBox status code.
3271 * @param pVM The cross context VM structure.
3272 */
3273static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3274{
3275 /*
3276 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3277 * when the host does not support it.
3278 */
3279 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3280 if ( !fGstVmwriteAll
3281 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3282 { /* likely. */ }
3283 else
3284 {
3285 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3286 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3287 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3288 }
3289
3290 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3291 uint32_t cRwFields = 0;
3292 uint32_t cRoFields = 0;
3293 for (uint32_t i = 0; i < cVmcsFields; i++)
3294 {
3295 VMXVMCSFIELD VmcsField;
3296 VmcsField.u = g_aVmcsFields[i];
3297
3298 /*
3299 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3300 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3301 * in the shadow VMCS fields array as they would be redundant.
3302 *
3303 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3304 * we must not include it in the shadow VMCS fields array. Guests attempting to
3305 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3306 * the required behavior.
3307 */
3308 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3309 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3310 {
3311 /*
3312 * Read-only fields are placed in a separate array so that while syncing shadow
3313 * VMCS fields later (which is more performance critical) we can avoid branches.
3314 *
3315 * However, if the guest can write to all fields (including read-only fields),
3316 * we treat it a as read/write field. Otherwise, writing to these fields would
3317 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3318 */
3319 if ( fGstVmwriteAll
3320 || !HMVmxIsVmcsFieldReadOnly(VmcsField.u))
3321 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3322 else
3323 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3324 }
3325 }
3326
3327 /* Update the counts. */
3328 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3329 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3330 return VINF_SUCCESS;
3331}
3332
3333
3334/**
3335 * Sets up the VMREAD and VMWRITE bitmaps.
3336 *
3337 * @param pVM The cross context VM structure.
3338 */
3339static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3340{
3341 /*
3342 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3343 */
3344 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3345 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3346 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3347 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3348 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3349
3350 /*
3351 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3352 * VMREAD and VMWRITE bitmaps.
3353 */
3354 {
3355 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3356 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3357 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3358 {
3359 uint32_t const uVmcsField = paShadowVmcsFields[i];
3360 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3361 Assert(uVmcsField >> 3 < cbBitmap);
3362 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3363 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3364 }
3365 }
3366
3367 /*
3368 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3369 * if the host supports VMWRITE to all supported VMCS fields.
3370 */
3371 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3372 {
3373 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3374 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3375 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3376 {
3377 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3378 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3379 Assert(uVmcsField >> 3 < cbBitmap);
3380 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3381 }
3382 }
3383}
3384#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3385
3386
3387/**
3388 * Sets up the virtual-APIC page address for the VMCS.
3389 *
3390 * @returns VBox status code.
3391 * @param pVCpu The cross context virtual CPU structure.
3392 * @param pVmcsInfo The VMCS info. object.
3393 */
3394DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3395{
3396 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3397 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3398 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3399 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3400 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3401}
3402
3403
3404/**
3405 * Sets up the MSR-bitmap address for the VMCS.
3406 *
3407 * @returns VBox status code.
3408 * @param pVCpu The cross context virtual CPU structure.
3409 * @param pVmcsInfo The VMCS info. object.
3410 */
3411DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3412{
3413 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3414 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3415 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3416 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3417 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3418}
3419
3420
3421/**
3422 * Sets up the APIC-access page address for the VMCS.
3423 *
3424 * @returns VBox status code.
3425 * @param pVCpu The cross context virtual CPU structure.
3426 */
3427DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3428{
3429 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3430 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3431 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3432 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3433}
3434
3435
3436#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3437/**
3438 * Sets up the VMREAD bitmap address for the VMCS.
3439 *
3440 * @returns VBox status code.
3441 * @param pVCpu The cross context virtual CPU structure.
3442 */
3443DECLINLINE(int) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3444{
3445 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3446 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3447 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3448 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3449}
3450
3451
3452/**
3453 * Sets up the VMWRITE bitmap address for the VMCS.
3454 *
3455 * @returns VBox status code.
3456 * @param pVCpu The cross context virtual CPU structure.
3457 */
3458DECLINLINE(int) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3459{
3460 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3461 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3462 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3463 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3464}
3465#endif
3466
3467
3468/**
3469 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3470 * in the VMCS.
3471 *
3472 * @returns VBox status code.
3473 * @param pVCpu The cross context virtual CPU structure.
3474 * @param pVmcsInfo The VMCS info. object.
3475 */
3476DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3477{
3478 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3479
3480 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3481 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3482 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3483
3484 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3485 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3486 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3487
3488 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3489 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3490 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3491
3492 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
3493 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
3494 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
3495 AssertRCReturn(rc, rc);
3496 return VINF_SUCCESS;
3497}
3498
3499
3500/**
3501 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3502 *
3503 * @param pVCpu The cross context virtual CPU structure.
3504 * @param pVmcsInfo The VMCS info. object.
3505 */
3506static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3507{
3508 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3509
3510 /*
3511 * The guest can access the following MSRs (read, write) without causing
3512 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3513 */
3514 PVM pVM = pVCpu->CTX_SUFF(pVM);
3515 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3516 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3517 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3518 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3519 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3520
3521 /*
3522 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3523 * associated with then. We never need to intercept access (writes need to be
3524 * executed without causing a VM-exit, reads will #GP fault anyway).
3525 *
3526 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3527 * read/write them. We swap the the guest/host MSR value using the
3528 * auto-load/store MSR area.
3529 */
3530 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3531 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3532 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3533 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3534 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3535 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3536
3537#if HC_ARCH_BITS == 64
3538 /*
3539 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3540 * required for 64-bit guests.
3541 */
3542 if (pVM->hm.s.fAllow64BitGuests)
3543 {
3544 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3545 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3546 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3547 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3548 }
3549#endif
3550
3551 /*
3552 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3553 */
3554#ifdef VBOX_STRICT
3555 Assert(pVmcsInfo->pvMsrBitmap);
3556 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3557 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3558#endif
3559}
3560
3561
3562/**
3563 * Sets up pin-based VM-execution controls in the VMCS.
3564 *
3565 * @returns VBox status code.
3566 * @param pVCpu The cross context virtual CPU structure.
3567 * @param pVmcsInfo The VMCS info. object.
3568 */
3569static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3570{
3571 PVM pVM = pVCpu->CTX_SUFF(pVM);
3572 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3573 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3574
3575 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3576 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3577
3578 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3579 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3580
3581 /* Enable the VMX-preemption timer. */
3582 if (pVM->hm.s.vmx.fUsePreemptTimer)
3583 {
3584 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3585 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3586 }
3587
3588#if 0
3589 /* Enable posted-interrupt processing. */
3590 if (pVM->hm.s.fPostedIntrs)
3591 {
3592 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3593 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3594 fVal |= VMX_PIN_CTLS_POSTED_INT;
3595 }
3596#endif
3597
3598 if ((fVal & fZap) != fVal)
3599 {
3600 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3601 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3602 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3603 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3604 }
3605
3606 /* Commit it to the VMCS and update our cache. */
3607 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3608 AssertRCReturn(rc, rc);
3609 pVmcsInfo->u32PinCtls = fVal;
3610
3611 return VINF_SUCCESS;
3612}
3613
3614
3615/**
3616 * Sets up secondary processor-based VM-execution controls in the VMCS.
3617 *
3618 * @returns VBox status code.
3619 * @param pVCpu The cross context virtual CPU structure.
3620 * @param pVmcsInfo The VMCS info. object.
3621 */
3622static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3623{
3624 PVM pVM = pVCpu->CTX_SUFF(pVM);
3625 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3626 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3627
3628 /* WBINVD causes a VM-exit. */
3629 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3630 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3631
3632 /* Enable EPT (aka nested-paging). */
3633 if (pVM->hm.s.fNestedPaging)
3634 fVal |= VMX_PROC_CTLS2_EPT;
3635
3636 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3637 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3638 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3639 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3640 fVal |= VMX_PROC_CTLS2_INVPCID;
3641
3642 /* Enable VPID. */
3643 if (pVM->hm.s.vmx.fVpid)
3644 fVal |= VMX_PROC_CTLS2_VPID;
3645
3646 /* Enable unrestricted guest execution. */
3647 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3648 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3649
3650#if 0
3651 if (pVM->hm.s.fVirtApicRegs)
3652 {
3653 /* Enable APIC-register virtualization. */
3654 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3655 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3656
3657 /* Enable virtual-interrupt delivery. */
3658 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3659 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3660 }
3661#endif
3662
3663 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3664 where the TPR shadow resides. */
3665 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3666 * done dynamically. */
3667 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3668 {
3669 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3670 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3671 AssertRCReturn(rc, rc);
3672 }
3673
3674 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3675 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3676 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3677 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3678 fVal |= VMX_PROC_CTLS2_RDTSCP;
3679
3680 /* Enable Pause-Loop exiting. */
3681 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3682 && pVM->hm.s.vmx.cPleGapTicks
3683 && pVM->hm.s.vmx.cPleWindowTicks)
3684 {
3685 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3686
3687 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3688 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3689 AssertRCReturn(rc, rc);
3690 }
3691
3692 if ((fVal & fZap) != fVal)
3693 {
3694 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3695 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3696 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3697 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3698 }
3699
3700 /* Commit it to the VMCS and update our cache. */
3701 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3702 AssertRCReturn(rc, rc);
3703 pVmcsInfo->u32ProcCtls2 = fVal;
3704
3705 return VINF_SUCCESS;
3706}
3707
3708
3709/**
3710 * Sets up processor-based VM-execution controls in the VMCS.
3711 *
3712 * @returns VBox status code.
3713 * @param pVCpu The cross context virtual CPU structure.
3714 * @param pVmcsInfo The VMCS info. object.
3715 */
3716static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3717{
3718 PVM pVM = pVCpu->CTX_SUFF(pVM);
3719
3720 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3721 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3722
3723 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3724 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3725 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3726 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3727 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3728 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3729 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3730
3731 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3732 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3733 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3734 {
3735 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3736 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3737 }
3738
3739 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3740 if (!pVM->hm.s.fNestedPaging)
3741 {
3742 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3743 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3744 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3745 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3746 }
3747
3748 /* Use TPR shadowing if supported by the CPU. */
3749 if ( PDMHasApic(pVM)
3750 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3751 {
3752 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3753 /* CR8 writes cause a VM-exit based on TPR threshold. */
3754 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3755 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3756 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3757 AssertRCReturn(rc, rc);
3758 }
3759 else
3760 {
3761 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3762 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3763 if (pVM->hm.s.fAllow64BitGuests)
3764 {
3765 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3766 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3767 }
3768 }
3769
3770 /* Use MSR-bitmaps if supported by the CPU. */
3771 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3772 {
3773 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3774 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3775 AssertRCReturn(rc, rc);
3776 }
3777
3778 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3779 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3780 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3781
3782 if ((fVal & fZap) != fVal)
3783 {
3784 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3785 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3786 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
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_EXEC, fVal);
3792 AssertRCReturn(rc, rc);
3793 pVmcsInfo->u32ProcCtls = fVal;
3794
3795 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3796 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3797 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3798
3799 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3800 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3801 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3802
3803 /* Sanity check, should not really happen. */
3804 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3805 { /* likely */ }
3806 else
3807 {
3808 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3809 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3810 }
3811
3812 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3813 return VINF_SUCCESS;
3814}
3815
3816
3817/**
3818 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3819 * Processor-based VM-execution) control fields in the VMCS.
3820 *
3821 * @returns VBox status code.
3822 * @param pVCpu The cross context virtual CPU structure.
3823 * @param pVmcsInfo The VMCS info. object.
3824 */
3825static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3826{
3827#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3828 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3829 {
3830 int rc = hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3831 rc |= hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3832 if (RT_SUCCESS(rc))
3833 { /* likely */ }
3834 else
3835 {
3836 LogRelFunc(("Failed to setup VMREAD/VMWRITE bitmap addresses. rc=%Rrc\n", rc));
3837 return rc;
3838 }
3839 }
3840#endif
3841
3842 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3843 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3844 if (RT_SUCCESS(rc))
3845 {
3846 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3847 if (RT_SUCCESS(rc))
3848 {
3849 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3850 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3851 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3852 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3853 if (RT_SUCCESS(rc))
3854 {
3855 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3856 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3857 return VINF_SUCCESS;
3858 }
3859 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3860 }
3861 else
3862 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3863 }
3864 else
3865 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3866 return rc;
3867}
3868
3869
3870/**
3871 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3872 *
3873 * We shall setup those exception intercepts that don't change during the
3874 * lifetime of the VM here. The rest are done dynamically while loading the
3875 * guest state.
3876 *
3877 * @returns VBox status code.
3878 * @param pVCpu The cross context virtual CPU structure.
3879 * @param pVmcsInfo The VMCS info. object.
3880 */
3881static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3882{
3883 /*
3884 * The following exceptions are always intercepted:
3885 *
3886 * #AC - To prevent the guest from hanging the CPU.
3887 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3888 * recursive #DBs can cause a CPU hang.
3889 * #PF - To sync our shadow page tables when nested-paging is not used.
3890 */
3891 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3892 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3893 | RT_BIT(X86_XCPT_DB)
3894 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3895
3896 /* Commit it to the VMCS. */
3897 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3898 AssertRCReturn(rc, rc);
3899
3900 /* Update our cache of the exception bitmap. */
3901 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3902 return VINF_SUCCESS;
3903}
3904
3905
3906#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3907/**
3908 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3909 *
3910 * @returns VBox status code.
3911 * @param pVCpu The cross context virtual CPU structure.
3912 * @param pVmcsInfo The VMCS info. object.
3913 */
3914static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3915{
3916 PVM pVM = pVCpu->CTX_SUFF(pVM);
3917 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3918 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3919 if (RT_SUCCESS(rc))
3920 {
3921 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3922 if (RT_SUCCESS(rc))
3923 {
3924 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3925 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3926 if (RT_SUCCESS(rc))
3927 {
3928 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3929 rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3930 if (RT_SUCCESS(rc))
3931 return VINF_SUCCESS;
3932
3933 LogRelFunc(("Failed to set up the APIC-access address in the nested-guest VMCS. rc=%Rrc\n", rc));
3934 }
3935 else
3936 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
3937 }
3938 else
3939 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3940 }
3941 else
3942 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
3943
3944 return rc;
3945}
3946#endif
3947
3948
3949/**
3950 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3951 * VMX.
3952 *
3953 * @returns VBox status code.
3954 * @param pVCpu The cross context virtual CPU structure.
3955 * @param pVmcsInfo The VMCS info. object.
3956 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3957 */
3958static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3959{
3960 Assert(pVmcsInfo->pvVmcs);
3961 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3962
3963 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3964 PVM pVM = pVCpu->CTX_SUFF(pVM);
3965 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3966 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3967
3968 LogFlowFunc(("\n"));
3969
3970 /*
3971 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3972 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3973 */
3974 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3975 if (RT_SUCCESS(rc))
3976 {
3977 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3978 if (RT_SUCCESS(rc))
3979 {
3980 if (!fIsNstGstVmcs)
3981 {
3982 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3983 if (RT_SUCCESS(rc))
3984 {
3985 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3986 if (RT_SUCCESS(rc))
3987 {
3988 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3989 if (RT_SUCCESS(rc))
3990 {
3991 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3992 if (RT_SUCCESS(rc))
3993 {
3994#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3995 /*
3996 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3997 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3998 * making it fit for use when VMCS shadowing is later enabled.
3999 */
4000 if (pVmcsInfo->pvShadowVmcs)
4001 {
4002 VMXVMCSREVID VmcsRevId;
4003 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4004 VmcsRevId.n.fIsShadowVmcs = 1;
4005 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4006 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4007 if (RT_SUCCESS(rc))
4008 { /* likely */ }
4009 else
4010 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4011 }
4012#endif
4013 }
4014 else
4015 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
4016 }
4017 else
4018 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4019 }
4020 else
4021 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4022 }
4023 else
4024 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4025 }
4026 else
4027 {
4028#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4029 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4030 if (RT_SUCCESS(rc))
4031 { /* likely */ }
4032 else
4033 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4034#else
4035 AssertFailed();
4036#endif
4037 }
4038 }
4039 else
4040 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4041 }
4042 else
4043 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4044
4045 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4046 if (RT_SUCCESS(rc))
4047 {
4048 rc = hmR0VmxClearVmcs(pVmcsInfo);
4049 if (RT_SUCCESS(rc))
4050 { /* likely */ }
4051 else
4052 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4053 }
4054
4055 /*
4056 * Update the last-error record both for failures and success, so we
4057 * can propagate the status code back to ring-3 for diagnostics.
4058 */
4059 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4060 NOREF(pszVmcs);
4061 return rc;
4062}
4063
4064
4065/**
4066 * Does global VT-x initialization (called during module initialization).
4067 *
4068 * @returns VBox status code.
4069 */
4070VMMR0DECL(int) VMXR0GlobalInit(void)
4071{
4072#ifdef HMVMX_USE_FUNCTION_TABLE
4073 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4074# ifdef VBOX_STRICT
4075 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4076 Assert(g_apfnVMExitHandlers[i]);
4077# endif
4078#endif
4079 return VINF_SUCCESS;
4080}
4081
4082
4083/**
4084 * Does global VT-x termination (called during module termination).
4085 */
4086VMMR0DECL(void) VMXR0GlobalTerm()
4087{
4088 /* Nothing to do currently. */
4089}
4090
4091
4092/**
4093 * Sets up and activates VT-x on the current CPU.
4094 *
4095 * @returns VBox status code.
4096 * @param pHostCpu The HM physical-CPU structure.
4097 * @param pVM The cross context VM structure. Can be
4098 * NULL after a host resume operation.
4099 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4100 * fEnabledByHost is @c true).
4101 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4102 * @a fEnabledByHost is @c true).
4103 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4104 * enable VT-x on the host.
4105 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4106 */
4107VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4108 PCSUPHWVIRTMSRS pHwvirtMsrs)
4109{
4110 AssertPtr(pHostCpu);
4111 AssertPtr(pHwvirtMsrs);
4112 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4113
4114 /* Enable VT-x if it's not already enabled by the host. */
4115 if (!fEnabledByHost)
4116 {
4117 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4118 if (RT_FAILURE(rc))
4119 return rc;
4120 }
4121
4122 /*
4123 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4124 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4125 * invalidated when flushing by VPID.
4126 */
4127 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4128 {
4129 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4130 pHostCpu->fFlushAsidBeforeUse = false;
4131 }
4132 else
4133 pHostCpu->fFlushAsidBeforeUse = true;
4134
4135 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4136 ++pHostCpu->cTlbFlushes;
4137
4138 return VINF_SUCCESS;
4139}
4140
4141
4142/**
4143 * Deactivates VT-x on the current CPU.
4144 *
4145 * @returns VBox status code.
4146 * @param pvCpuPage Pointer to the VMXON region.
4147 * @param HCPhysCpuPage Physical address of the VMXON region.
4148 *
4149 * @remarks This function should never be called when SUPR0EnableVTx() or
4150 * similar was used to enable VT-x on the host.
4151 */
4152VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4153{
4154 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4155
4156 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4157 return hmR0VmxLeaveRootMode();
4158}
4159
4160
4161/**
4162 * Does per-VM VT-x initialization.
4163 *
4164 * @returns VBox status code.
4165 * @param pVM The cross context VM structure.
4166 */
4167VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4168{
4169 AssertPtr(pVM);
4170 LogFlowFunc(("pVM=%p\n", pVM));
4171
4172 int rc = hmR0VmxStructsAlloc(pVM);
4173 if (RT_FAILURE(rc))
4174 {
4175 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4176 return rc;
4177 }
4178
4179 return VINF_SUCCESS;
4180}
4181
4182
4183/**
4184 * Does per-VM VT-x termination.
4185 *
4186 * @returns VBox status code.
4187 * @param pVM The cross context VM structure.
4188 */
4189VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4190{
4191 AssertPtr(pVM);
4192 LogFlowFunc(("pVM=%p\n", pVM));
4193
4194#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4195 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4196 {
4197 Assert(pVM->hm.s.vmx.pvScratch);
4198 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4199 }
4200#endif
4201 hmR0VmxStructsFree(pVM);
4202 return VINF_SUCCESS;
4203}
4204
4205
4206/**
4207 * Sets up the VM for execution using hardware-assisted VMX.
4208 * This function is only called once per-VM during initialization.
4209 *
4210 * @returns VBox status code.
4211 * @param pVM The cross context VM structure.
4212 */
4213VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4214{
4215 AssertPtr(pVM);
4216 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4217
4218 LogFlowFunc(("pVM=%p\n", pVM));
4219
4220 /*
4221 * At least verify if VMX is enabled, since we can't check if we're in
4222 * VMX root mode or not without causing a #GP.
4223 */
4224 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4225 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4226 { /* likely */ }
4227 else
4228 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4229
4230 /*
4231 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4232 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4233 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4234 */
4235 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4236 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4237 || !pVM->hm.s.vmx.pRealModeTSS))
4238 {
4239 LogRelFunc(("Invalid real-on-v86 state.\n"));
4240 return VERR_INTERNAL_ERROR;
4241 }
4242
4243 /* Initialize these always, see hmR3InitFinalizeR0().*/
4244 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4245 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4246
4247 /* Setup the tagged-TLB flush handlers. */
4248 int rc = hmR0VmxSetupTaggedTlb(pVM);
4249 if (RT_FAILURE(rc))
4250 {
4251 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4252 return rc;
4253 }
4254
4255#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4256 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4257 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4258 {
4259 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4260 if (RT_SUCCESS(rc))
4261 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4262 else
4263 {
4264 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4265 return rc;
4266 }
4267 }
4268#endif
4269
4270 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4271 {
4272 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4273 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4274
4275 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4276 if (RT_SUCCESS(rc))
4277 {
4278#if HC_ARCH_BITS == 32
4279 hmR0VmxInitVmcsReadCache(pVCpu);
4280#endif
4281#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4282 if (pVM->cpum.ro.GuestFeatures.fVmx)
4283 {
4284 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4285 if (RT_SUCCESS(rc))
4286 { /* likely */ }
4287 else
4288 {
4289 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4290 return rc;
4291 }
4292 }
4293#endif
4294 }
4295 else
4296 {
4297 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4298 return rc;
4299 }
4300 }
4301
4302 return VINF_SUCCESS;
4303}
4304
4305
4306#if HC_ARCH_BITS == 32
4307# ifdef VBOX_ENABLE_64_BITS_GUESTS
4308/**
4309 * Check if guest state allows safe use of 32-bit switcher again.
4310 *
4311 * Segment bases and protected mode structures must be 32-bit addressable
4312 * because the 32-bit switcher will ignore high dword when writing these VMCS
4313 * fields. See @bugref{8432} for details.
4314 *
4315 * @returns true if safe, false if must continue to use the 64-bit switcher.
4316 * @param pCtx Pointer to the guest-CPU context.
4317 *
4318 * @remarks No-long-jump zone!!!
4319 */
4320static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
4321{
4322 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
4323 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
4324 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4325 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4326 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
4327 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4328 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
4329 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
4330 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4331 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4332
4333 /* All good, bases are 32-bit. */
4334 return true;
4335}
4336# endif /* VBOX_ENABLE_64_BITS_GUESTS */
4337
4338# ifdef VBOX_STRICT
4339static bool hmR0VmxIsValidWriteFieldInCache(uint32_t idxField)
4340{
4341 switch (idxField)
4342 {
4343 case VMX_VMCS_GUEST_RIP:
4344 case VMX_VMCS_GUEST_RSP:
4345 case VMX_VMCS_GUEST_SYSENTER_EIP:
4346 case VMX_VMCS_GUEST_SYSENTER_ESP:
4347 case VMX_VMCS_GUEST_GDTR_BASE:
4348 case VMX_VMCS_GUEST_IDTR_BASE:
4349 case VMX_VMCS_GUEST_CS_BASE:
4350 case VMX_VMCS_GUEST_DS_BASE:
4351 case VMX_VMCS_GUEST_ES_BASE:
4352 case VMX_VMCS_GUEST_FS_BASE:
4353 case VMX_VMCS_GUEST_GS_BASE:
4354 case VMX_VMCS_GUEST_SS_BASE:
4355 case VMX_VMCS_GUEST_LDTR_BASE:
4356 case VMX_VMCS_GUEST_TR_BASE:
4357 case VMX_VMCS_GUEST_CR3:
4358 return true;
4359 }
4360 return false;
4361}
4362
4363static bool hmR0VmxIsValidReadFieldInCache(uint32_t idxField)
4364{
4365 switch (idxField)
4366 {
4367 /* Read-only fields. */
4368 case VMX_VMCS_RO_EXIT_QUALIFICATION:
4369 return true;
4370 }
4371 /* Remaining readable fields should also be writable. */
4372 return hmR0VmxIsValidWriteFieldInCache(idxField);
4373}
4374# endif /* VBOX_STRICT */
4375
4376
4377/**
4378 * Executes the specified handler in 64-bit mode.
4379 *
4380 * @returns VBox status code (no informational status codes).
4381 * @param pVCpu The cross context virtual CPU structure.
4382 * @param enmOp The operation to perform.
4383 * @param cParams Number of parameters.
4384 * @param paParam Array of 32-bit parameters.
4385 */
4386VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
4387{
4388 AssertPtr(pVCpu);
4389 PVM pVM = pVCpu->CTX_SUFF(pVM);
4390 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
4391 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
4392 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
4393 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
4394
4395#ifdef VBOX_STRICT
4396 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
4397 Assert(hmR0VmxIsValidWriteFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
4398
4399 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
4400 Assert(hmR0VmxIsValidReadFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
4401#endif
4402
4403 /* Disable interrupts. */
4404 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
4405
4406#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
4407 RTCPUID idHostCpu = RTMpCpuId();
4408 CPUMR0SetLApic(pVCpu, idHostCpu);
4409#endif
4410
4411 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
4412
4413 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4414 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4415
4416 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
4417 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4418 hmR0VmxClearVmcs(pVmcsInfo);
4419
4420 /* Leave VMX root mode and disable VMX. */
4421 VMXDisable();
4422 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4423
4424 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
4425 CPUMSetHyperEIP(pVCpu, enmOp);
4426 for (int i = (int)cParams - 1; i >= 0; i--)
4427 CPUMPushHyper(pVCpu, paParam[i]);
4428
4429 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
4430
4431 /* Call the switcher. */
4432 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
4433 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
4434
4435 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
4436 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
4437
4438 /* Re-enter VMX root mode. */
4439 int rc2 = VMXEnable(HCPhysCpuPage);
4440 if (RT_FAILURE(rc2))
4441 {
4442 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4443 ASMSetFlags(fOldEFlags);
4444 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
4445 return rc2;
4446 }
4447
4448 /* Restore the VMCS as the current VMCS. */
4449 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
4450 AssertRC(rc2);
4451 Assert(!(ASMGetFlags() & X86_EFL_IF));
4452 ASMSetFlags(fOldEFlags);
4453 return rc;
4454}
4455
4456
4457/**
4458 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
4459 * supporting 64-bit guests.
4460 *
4461 * @returns VBox status code.
4462 * @param fResume Whether to VMLAUNCH or VMRESUME.
4463 * @param pCtx Pointer to the guest-CPU context.
4464 * @param pCache Pointer to the VMCS batch cache.
4465 * @param pVM The cross context VM structure.
4466 * @param pVCpu The cross context virtual CPU structure.
4467 */
4468DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
4469{
4470 NOREF(fResume);
4471
4472 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4473 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4474 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4475
4476#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4477 pCache->uPos = 1;
4478 pCache->interPD = PGMGetInterPaeCR3(pVM);
4479 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
4480#endif
4481
4482#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4483 pCache->TestIn.HCPhysCpuPage = 0;
4484 pCache->TestIn.HCPhysVmcs = 0;
4485 pCache->TestIn.pCache = 0;
4486 pCache->TestOut.HCPhysVmcs = 0;
4487 pCache->TestOut.pCache = 0;
4488 pCache->TestOut.pCtx = 0;
4489 pCache->TestOut.eflags = 0;
4490#else
4491 NOREF(pCache);
4492#endif
4493
4494 uint32_t aParam[10];
4495 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
4496 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
4497 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
4498 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
4499 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
4500 aParam[5] = 0;
4501 aParam[6] = VM_RC_ADDR(pVM, pVM);
4502 aParam[7] = 0;
4503 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
4504 aParam[9] = 0;
4505
4506#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4507 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
4508 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
4509#endif
4510 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
4511
4512#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4513 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
4514 Assert(pCtx->dr[4] == 10);
4515 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
4516#endif
4517
4518#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4519 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
4520 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4521 pVmcsInfo->HCPhysVmcs));
4522 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4523 pCache->TestOut.HCPhysVmcs));
4524 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
4525 pCache->TestOut.pCache));
4526 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
4527 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
4528 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
4529 pCache->TestOut.pCtx));
4530 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
4531#endif
4532 NOREF(pCtx);
4533 return rc;
4534}
4535#endif
4536
4537
4538/**
4539 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4540 * the VMCS.
4541 *
4542 * @returns VBox status code.
4543 */
4544static int hmR0VmxExportHostControlRegs(void)
4545{
4546 RTCCUINTREG uReg = ASMGetCR0();
4547 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
4548 AssertRCReturn(rc, rc);
4549
4550 uReg = ASMGetCR3();
4551 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
4552 AssertRCReturn(rc, rc);
4553
4554 uReg = ASMGetCR4();
4555 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
4556 AssertRCReturn(rc, rc);
4557 return rc;
4558}
4559
4560
4561/**
4562 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4563 * the host-state area in the VMCS.
4564 *
4565 * @returns VBox status code.
4566 * @param pVCpu The cross context virtual CPU structure.
4567 */
4568static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4569{
4570#if HC_ARCH_BITS == 64
4571/**
4572 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4573 * requirements. See hmR0VmxExportHostSegmentRegs().
4574 */
4575# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
4576 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4577 { \
4578 bool fValidSelector = true; \
4579 if ((selValue) & X86_SEL_LDT) \
4580 { \
4581 uint32_t uAttr = ASMGetSegAttr((selValue)); \
4582 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4583 } \
4584 if (fValidSelector) \
4585 { \
4586 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
4587 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
4588 } \
4589 (selValue) = 0; \
4590 }
4591
4592 /*
4593 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4594 * will be messed up. We should -not- save the messed up state without restoring
4595 * the original host-state, see @bugref{7240}.
4596 *
4597 * This apparently can happen (most likely the FPU changes), deal with it rather than
4598 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4599 */
4600 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4601 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4602 {
4603 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4604 pVCpu->idCpu));
4605 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4606 }
4607 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4608#else
4609 RT_NOREF(pVCpu);
4610#endif
4611
4612 /*
4613 * Host DS, ES, FS and GS segment registers.
4614 */
4615#if HC_ARCH_BITS == 64
4616 RTSEL uSelDS = ASMGetDS();
4617 RTSEL uSelES = ASMGetES();
4618 RTSEL uSelFS = ASMGetFS();
4619 RTSEL uSelGS = ASMGetGS();
4620#else
4621 RTSEL uSelDS = 0;
4622 RTSEL uSelES = 0;
4623 RTSEL uSelFS = 0;
4624 RTSEL uSelGS = 0;
4625#endif
4626
4627 /*
4628 * Host CS and SS segment registers.
4629 */
4630 RTSEL uSelCS = ASMGetCS();
4631 RTSEL uSelSS = ASMGetSS();
4632
4633 /*
4634 * Host TR segment register.
4635 */
4636 RTSEL uSelTR = ASMGetTR();
4637
4638#if HC_ARCH_BITS == 64
4639 /*
4640 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4641 * gain VM-entry and restore them before we get preempted.
4642 *
4643 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4644 */
4645 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4646 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4647 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4648 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4649# undef VMXLOCAL_ADJUST_HOST_SEG
4650#endif
4651
4652 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4653 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4654 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4655 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4656 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4657 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4658 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4659 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4660 Assert(uSelCS);
4661 Assert(uSelTR);
4662
4663 /* Write these host selector fields into the host-state area in the VMCS. */
4664 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
4665 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
4666#if HC_ARCH_BITS == 64
4667 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
4668 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
4669 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
4670 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
4671#else
4672 NOREF(uSelDS);
4673 NOREF(uSelES);
4674 NOREF(uSelFS);
4675 NOREF(uSelGS);
4676#endif
4677 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
4678 AssertRCReturn(rc, rc);
4679
4680 /*
4681 * Host GDTR and IDTR.
4682 */
4683 RTGDTR Gdtr;
4684 RTIDTR Idtr;
4685 RT_ZERO(Gdtr);
4686 RT_ZERO(Idtr);
4687 ASMGetGDTR(&Gdtr);
4688 ASMGetIDTR(&Idtr);
4689 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
4690 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
4691 AssertRCReturn(rc, rc);
4692
4693#if HC_ARCH_BITS == 64
4694 /*
4695 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4696 * them to the maximum limit (0xffff) on every VM-exit.
4697 */
4698 if (Gdtr.cbGdt != 0xffff)
4699 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4700
4701 /*
4702 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4703 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4704 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4705 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4706 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4707 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4708 * at 0xffff on hosts where we are sure it won't cause trouble.
4709 */
4710# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4711 if (Idtr.cbIdt < 0x0fff)
4712# else
4713 if (Idtr.cbIdt != 0xffff)
4714# endif
4715 {
4716 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4717 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4718 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4719 }
4720#endif
4721
4722 /*
4723 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4724 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4725 * RPL should be too in most cases.
4726 */
4727 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4728 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4729
4730 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4731#if HC_ARCH_BITS == 64
4732 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4733
4734 /*
4735 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4736 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4737 * restoration if the host has something else. Task switching is not supported in 64-bit
4738 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4739 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4740 *
4741 * [1] See Intel spec. 3.5 "System Descriptor Types".
4742 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4743 */
4744 PVM pVM = pVCpu->CTX_SUFF(pVM);
4745 Assert(pDesc->System.u4Type == 11);
4746 if ( pDesc->System.u16LimitLow != 0x67
4747 || pDesc->System.u4LimitHigh)
4748 {
4749 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4750 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4751 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4752 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4753 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4754 }
4755
4756 /*
4757 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4758 */
4759 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4760 {
4761 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4762 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4763 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4764 {
4765 /* The GDT is read-only but the writable GDT is available. */
4766 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4767 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4768 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4769 AssertRCReturn(rc, rc);
4770 }
4771 }
4772#else
4773 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4774#endif
4775 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4776 AssertRCReturn(rc, rc);
4777
4778 /*
4779 * Host FS base and GS base.
4780 */
4781#if HC_ARCH_BITS == 64
4782 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4783 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4784 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4785 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4786 AssertRCReturn(rc, rc);
4787
4788 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4789 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4790 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4791 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4792 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4793#endif
4794 return VINF_SUCCESS;
4795}
4796
4797
4798/**
4799 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4800 * host-state area of the VMCS.
4801 *
4802 * These MSRs will be automatically restored on the host after every successful
4803 * VM-exit.
4804 *
4805 * @returns VBox status code.
4806 * @param pVCpu The cross context virtual CPU structure.
4807 *
4808 * @remarks No-long-jump zone!!!
4809 */
4810static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4811{
4812 AssertPtr(pVCpu);
4813
4814 /*
4815 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4816 * rather than swapping them on every VM-entry.
4817 */
4818 hmR0VmxLazySaveHostMsrs(pVCpu);
4819
4820 /*
4821 * Host Sysenter MSRs.
4822 */
4823 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4824#if HC_ARCH_BITS == 32
4825 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4826 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4827#else
4828 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4829 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4830#endif
4831 AssertRCReturn(rc, rc);
4832
4833 /*
4834 * Host EFER MSR.
4835 *
4836 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4837 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4838 */
4839 PVM pVM = pVCpu->CTX_SUFF(pVM);
4840 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4841 {
4842 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4843 AssertRCReturn(rc, rc);
4844 }
4845
4846 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4847 * hmR0VmxExportGuestEntryExitCtls(). */
4848
4849 return VINF_SUCCESS;
4850}
4851
4852
4853/**
4854 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4855 *
4856 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4857 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4858 *
4859 * @returns true if we need to load guest EFER, false otherwise.
4860 * @param pVCpu The cross context virtual CPU structure.
4861 *
4862 * @remarks Requires EFER, CR4.
4863 * @remarks No-long-jump zone!!!
4864 */
4865static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4866{
4867#ifdef HMVMX_ALWAYS_SWAP_EFER
4868 RT_NOREF(pVCpu);
4869 return true;
4870#else
4871 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4872#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4873 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4874 if (CPUMIsGuestInLongModeEx(pCtx))
4875 return false;
4876#endif
4877
4878 PVM pVM = pVCpu->CTX_SUFF(pVM);
4879 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4880 uint64_t const u64GuestEfer = pCtx->msrEFER;
4881
4882 /*
4883 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4884 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4885 */
4886 if ( CPUMIsGuestInLongModeEx(pCtx)
4887 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4888 return true;
4889
4890 /*
4891 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4892 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4893 *
4894 * See Intel spec. 4.5 "IA-32e Paging".
4895 * See Intel spec. 4.1.1 "Three Paging Modes".
4896 *
4897 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4898 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4899 */
4900 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4901 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4902 if ( (pCtx->cr4 & X86_CR4_PAE)
4903 && (pCtx->cr0 & X86_CR0_PG)
4904 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4905 {
4906 /* Assert that host is NX capable. */
4907 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4908 return true;
4909 }
4910
4911 return false;
4912#endif
4913}
4914
4915/**
4916 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4917 * VMCS.
4918 *
4919 * This is typically required when the guest changes paging mode.
4920 *
4921 * @returns VBox status code.
4922 * @param pVCpu The cross context virtual CPU structure.
4923 * @param pVmxTransient The VMX-transient structure.
4924 *
4925 * @remarks Requires EFER.
4926 * @remarks No-long-jump zone!!!
4927 */
4928static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4929{
4930 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4931 {
4932 PVM pVM = pVCpu->CTX_SUFF(pVM);
4933 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4934
4935 /*
4936 * VM-entry controls.
4937 */
4938 {
4939 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4940 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4941
4942 /*
4943 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4944 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4945 *
4946 * For nested-guests, this is a mandatory VM-entry control. It's also
4947 * required because we do not want to leak host bits to the nested-guest.
4948 */
4949 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4950
4951 /*
4952 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4953 *
4954 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4955 * required to get the nested-guest working with hardware-assisted VMX execution.
4956 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4957 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4958 * here rather than while merging the guest VMCS controls.
4959 */
4960 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4961 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4962 else
4963 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4964
4965 /*
4966 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4967 *
4968 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4969 * regardless of whether the nested-guest VMCS specifies it because we are free to
4970 * load whatever MSRs we require and we do not need to modify the guest visible copy
4971 * of the VM-entry MSR load area.
4972 */
4973 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4974 && hmR0VmxShouldSwapEferMsr(pVCpu))
4975 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4976 else
4977 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4978
4979 /*
4980 * The following should -not- be set (since we're not in SMM mode):
4981 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4982 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4983 */
4984
4985 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4986 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4987
4988 if ((fVal & fZap) == fVal)
4989 { /* likely */ }
4990 else
4991 {
4992 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4993 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4994 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4995 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4996 }
4997
4998 /* Commit it to the VMCS. */
4999 if (pVmcsInfo->u32EntryCtls != fVal)
5000 {
5001 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5002 AssertRCReturn(rc, rc);
5003 pVmcsInfo->u32EntryCtls = fVal;
5004 }
5005 }
5006
5007 /*
5008 * VM-exit controls.
5009 */
5010 {
5011 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5012 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5013
5014 /*
5015 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5016 * supported the 1-setting of this bit.
5017 *
5018 * For nested-guests, we set the "save debug controls" as the converse
5019 * "load debug controls" is mandatory for nested-guests anyway.
5020 */
5021 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5022
5023 /*
5024 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5025 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5026 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5027 * hmR0VmxExportHostMsrs().
5028 *
5029 * For nested-guests, we always set this bit as we do not support 32-bit
5030 * hosts.
5031 */
5032#if HC_ARCH_BITS == 64
5033 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5034#else
5035 Assert(!pVmxTransient->fIsNestedGuest);
5036 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
5037 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
5038 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
5039 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
5040 {
5041 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
5042 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5043 }
5044 else
5045 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
5046#endif
5047
5048 /*
5049 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5050 *
5051 * For nested-guests, we should use the "save IA32_EFER" control if we also
5052 * used the "load IA32_EFER" control while exporting VM-entry controls.
5053 */
5054 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5055 && hmR0VmxShouldSwapEferMsr(pVCpu))
5056 {
5057 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5058 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5059 }
5060
5061 /*
5062 * Enable saving of the VMX-preemption timer value on VM-exit.
5063 * For nested-guests, currently not exposed/used.
5064 */
5065 if ( pVM->hm.s.vmx.fUsePreemptTimer
5066 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5067 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5068
5069 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5070 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5071
5072 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5073 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5074 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5075
5076 if ((fVal & fZap) == fVal)
5077 { /* likely */ }
5078 else
5079 {
5080 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5081 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5082 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5083 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5084 }
5085
5086 /* Commit it to the VMCS. */
5087 if (pVmcsInfo->u32ExitCtls != fVal)
5088 {
5089 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5090 AssertRCReturn(rc, rc);
5091 pVmcsInfo->u32ExitCtls = fVal;
5092 }
5093 }
5094
5095 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5096 }
5097 return VINF_SUCCESS;
5098}
5099
5100
5101/**
5102 * Sets the TPR threshold in the VMCS.
5103 *
5104 * @returns VBox status code.
5105 * @param pVCpu The cross context virtual CPU structure.
5106 * @param pVmcsInfo The VMCS info. object.
5107 * @param u32TprThreshold The TPR threshold (task-priority class only).
5108 */
5109DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5110{
5111 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5112 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5113 RT_NOREF2(pVCpu, pVmcsInfo);
5114 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5115}
5116
5117
5118/**
5119 * Exports the guest APIC TPR state into the VMCS.
5120 *
5121 * @returns VBox status code.
5122 * @param pVCpu The cross context virtual CPU structure.
5123 * @param pVmxTransient The VMX-transient structure.
5124 *
5125 * @remarks No-long-jump zone!!!
5126 */
5127static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5128{
5129 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5130 {
5131 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5132
5133 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5134 if (!pVmxTransient->fIsNestedGuest)
5135 {
5136 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5137 && APICIsEnabled(pVCpu))
5138 {
5139 /*
5140 * Setup TPR shadowing.
5141 */
5142 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5143 {
5144 bool fPendingIntr = false;
5145 uint8_t u8Tpr = 0;
5146 uint8_t u8PendingIntr = 0;
5147 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5148 AssertRCReturn(rc, rc);
5149
5150 /*
5151 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5152 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5153 * priority of the pending interrupt so we can deliver the interrupt. If there
5154 * are no interrupts pending, set threshold to 0 to not cause any
5155 * TPR-below-threshold VM-exits.
5156 */
5157 Assert(pVmcsInfo->pbVirtApic);
5158 pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR] = u8Tpr;
5159 uint32_t u32TprThreshold = 0;
5160 if (fPendingIntr)
5161 {
5162 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5163 (which is the Task-Priority Class). */
5164 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5165 const uint8_t u8TprPriority = u8Tpr >> 4;
5166 if (u8PendingPriority <= u8TprPriority)
5167 u32TprThreshold = u8PendingPriority;
5168 }
5169
5170 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
5171 AssertRCReturn(rc, rc);
5172 }
5173 }
5174 }
5175 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5176 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5177 }
5178 return VINF_SUCCESS;
5179}
5180
5181
5182/**
5183 * Gets the guest interruptibility-state.
5184 *
5185 * @returns Guest's interruptibility-state.
5186 * @param pVCpu The cross context virtual CPU structure.
5187 * @param pVmxTransient The VMX-transient structure.
5188 *
5189 * @remarks No-long-jump zone!!!
5190 */
5191static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5192{
5193 /*
5194 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5195 */
5196 uint32_t fIntrState = 0;
5197 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5198 {
5199 /* If inhibition is active, RIP and RFLAGS should've been updated
5200 (i.e. read previously from the VMCS or from ring-3). */
5201 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5202#ifdef VBOX_STRICT
5203 uint64_t const fExtrn = ASMAtomicUoReadU64(&pCtx->fExtrn);
5204 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5205 AssertMsg(!(fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)), ("%#x\n", fExtrn));
5206#endif
5207 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5208 {
5209 if (pCtx->eflags.Bits.u1IF)
5210 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5211 else
5212 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5213 }
5214 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5215 {
5216 /*
5217 * We can clear the inhibit force flag as even if we go back to the recompiler
5218 * without executing guest code in VT-x, the flag's condition to be cleared is
5219 * met and thus the cleared state is correct.
5220 */
5221 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5222 }
5223 }
5224
5225 /*
5226 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
5227 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
5228 * setting this would block host-NMIs and IRET will not clear the blocking.
5229 *
5230 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
5231 *
5232 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
5233 */
5234 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5235 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
5236 && CPUMIsGuestNmiBlocking(pVCpu))
5237 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5238
5239 return fIntrState;
5240}
5241
5242
5243/**
5244 * Exports the exception intercepts required for guest execution in the VMCS.
5245 *
5246 * @returns VBox status code.
5247 * @param pVCpu The cross context virtual CPU structure.
5248 * @param pVmxTransient The VMX-transient structure.
5249 *
5250 * @remarks No-long-jump zone!!!
5251 */
5252static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5253{
5254 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5255 {
5256 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5257 if ( !pVmxTransient->fIsNestedGuest
5258 && pVCpu->hm.s.fGIMTrapXcptUD)
5259 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5260 else
5261 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5262
5263 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5264 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5265 }
5266 return VINF_SUCCESS;
5267}
5268
5269
5270/**
5271 * Exports the guest's RIP into the guest-state area in the VMCS.
5272 *
5273 * @returns VBox status code.
5274 * @param pVCpu The cross context virtual CPU structure.
5275 *
5276 * @remarks No-long-jump zone!!!
5277 */
5278static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
5279{
5280 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5281 {
5282 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5283
5284 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5285 AssertRCReturn(rc, rc);
5286
5287 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5288 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5289 }
5290 return VINF_SUCCESS;
5291}
5292
5293
5294/**
5295 * Exports the guest's RSP into the guest-state area in the VMCS.
5296 *
5297 * @returns VBox status code.
5298 * @param pVCpu The cross context virtual CPU structure.
5299 *
5300 * @remarks No-long-jump zone!!!
5301 */
5302static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
5303{
5304 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5305 {
5306 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5307
5308 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5309 AssertRCReturn(rc, rc);
5310
5311 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5312 }
5313 return VINF_SUCCESS;
5314}
5315
5316
5317/**
5318 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5319 *
5320 * @returns VBox status code.
5321 * @param pVCpu The cross context virtual CPU structure.
5322 * @param pVmxTransient The VMX-transient structure.
5323 *
5324 * @remarks No-long-jump zone!!!
5325 */
5326static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5327{
5328 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5329 {
5330 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5331
5332 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5333 Let us assert it as such and use 32-bit VMWRITE. */
5334 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5335 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5336 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5337 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5338
5339 /*
5340 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5341 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5342 * can run the real-mode guest code under Virtual 8086 mode.
5343 */
5344 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5345 if (pVmcsInfo->RealMode.fRealOnV86Active)
5346 {
5347 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5348 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5349 Assert(!pVmxTransient->fIsNestedGuest);
5350 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5351 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5352 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5353 }
5354
5355 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5356 AssertRCReturn(rc, rc);
5357
5358 /*
5359 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5360 *
5361 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5362 * through the hypervisor debugger using EFLAGS.TF.
5363 */
5364 if ( !pVmxTransient->fIsNestedGuest
5365 && !pVCpu->hm.s.fSingleInstruction
5366 && fEFlags.Bits.u1TF)
5367 {
5368 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5369 * premature trips to ring-3 esp since IEM does not yet handle it. */
5370 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5371 AssertRCReturn(rc, rc);
5372 }
5373 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
5374 * nested-guest VMCS. */
5375
5376 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5377 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5378 }
5379 return VINF_SUCCESS;
5380}
5381
5382
5383#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5384/**
5385 * Copies the nested-guest VMCS to the shadow VMCS.
5386 *
5387 * @returns VBox status code.
5388 * @param pVCpu The cross context virtual CPU structure.
5389 * @param pVmcsInfo The VMCS info. object.
5390 *
5391 * @remarks No-long-jump zone!!!
5392 */
5393static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5394{
5395 PVM pVM = pVCpu->CTX_SUFF(pVM);
5396 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5397
5398 /*
5399 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5400 * current VMCS, as we may try saving guest lazy MSRs.
5401 *
5402 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5403 * calling the import VMCS code which is currently performing the guest MSR reads
5404 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5405 * and the rest of the VMX leave session machinery.
5406 */
5407 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5408
5409 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5410 if (RT_SUCCESS(rc))
5411 {
5412 /*
5413 * Copy all guest read/write VMCS fields.
5414 *
5415 * We don't check for VMWRITE failures here for performance reasons and
5416 * because they are not expected to fail, barring irrecoverable conditions
5417 * like hardware errors.
5418 */
5419 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5420 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5421 {
5422 uint64_t u64Val;
5423 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5424 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5425 VMXWriteVmcs64(uVmcsField, u64Val);
5426 }
5427
5428 /*
5429 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5430 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5431 */
5432 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5433 {
5434 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5435 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5436 {
5437 uint64_t u64Val;
5438 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5439 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5440 VMXWriteVmcs64(uVmcsField, u64Val);
5441 }
5442 }
5443
5444 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5445 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5446 }
5447
5448 ASMSetFlags(fEFlags);
5449 return rc;
5450}
5451
5452
5453/**
5454 * Copies the shadow VMCS to the nested-guest VMCS.
5455 *
5456 * @returns VBox status code.
5457 * @param pVCpu The cross context virtual CPU structure.
5458 * @param pVmcsInfo The VMCS info. object.
5459 *
5460 * @remarks Called with interrupts disabled.
5461 */
5462static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5463{
5464 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5465 PVM pVM = pVCpu->CTX_SUFF(pVM);
5466 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5467
5468 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5469 if (RT_SUCCESS(rc))
5470 {
5471 /*
5472 * Copy guest read/write fields from the shadow VMCS.
5473 * Guest read-only fields cannot be modified, so no need to copy them.
5474 *
5475 * We don't check for VMREAD failures here for performance reasons and
5476 * because they are not expected to fail, barring irrecoverable conditions
5477 * like hardware errors.
5478 */
5479 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5480 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5481 {
5482 uint64_t u64Val;
5483 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5484 VMXReadVmcs64(uVmcsField, &u64Val);
5485 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5486 }
5487
5488 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5489 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5490 }
5491 return rc;
5492}
5493
5494
5495/**
5496 * Enables VMCS shadowing for the given VMCS info. object.
5497 *
5498 * @param pVCpu The cross context virtual CPU structure.
5499 * @param pVmcsInfo The VMCS info. object.
5500 *
5501 * @remarks No-long-jump zone!!!
5502 */
5503static void hmR0VmxEnableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5504{
5505 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5506
5507 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5508 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5509 {
5510 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5511 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5512 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5513 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs);
5514 AssertRC(rc);
5515
5516 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5517 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5518 Log4Func(("Enabled\n"));
5519 }
5520}
5521
5522
5523/**
5524 * Disables VMCS shadowing for the given VMCS info. object.
5525 *
5526 * @param pVCpu The cross context virtual CPU structure.
5527 * @param pVmcsInfo The VMCS info. object.
5528 *
5529 * @remarks No-long-jump zone!!!
5530 */
5531static void hmR0VmxDisableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5532{
5533 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5534
5535 /*
5536 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5537 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5538 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5539 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5540 *
5541 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5542 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5543 */
5544 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5545 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5546 {
5547 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5548 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5549 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
5550 AssertRC(rc);
5551
5552 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5553 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5554 Log4Func(("Disabled\n"));
5555 }
5556}
5557#endif
5558
5559
5560/**
5561 * Exports the guest hardware-virtualization state.
5562 *
5563 * @returns VBox status code.
5564 * @param pVCpu The cross context virtual CPU structure.
5565 * @param pVmxTransient The VMX-transient structure.
5566 *
5567 * @remarks No-long-jump zone!!!
5568 */
5569static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5570{
5571 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5572 {
5573#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5574 /*
5575 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5576 * VMCS shadowing.
5577 */
5578 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5579 {
5580 /*
5581 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5582 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5583 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5584 *
5585 * We check for VMX root mode here in case the guest executes VMXOFF without
5586 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5587 * not clear the current VMCS pointer.
5588 */
5589 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5590 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5591 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5592 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5593 {
5594 /* Paranoia. */
5595 Assert(!pVmxTransient->fIsNestedGuest);
5596
5597 /*
5598 * For performance reasons, also check if the guest hypervisor's current VMCS
5599 * was newly loaded or modified before copying it to the shadow VMCS.
5600 */
5601 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5602 {
5603 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5604 AssertRCReturn(rc, rc);
5605 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5606 }
5607 hmR0VmxEnableVmcsShadowing(pVCpu, pVmcsInfo);
5608 }
5609 else
5610 hmR0VmxDisableVmcsShadowing(pVCpu, pVmcsInfo);
5611 }
5612#else
5613 NOREF(pVmxTransient);
5614#endif
5615 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5616 }
5617 return VINF_SUCCESS;
5618}
5619
5620
5621/**
5622 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5623 *
5624 * The guest FPU state is always pre-loaded hence we don't need to bother about
5625 * sharing FPU related CR0 bits between the guest and host.
5626 *
5627 * @returns VBox status code.
5628 * @param pVCpu The cross context virtual CPU structure.
5629 * @param pVmxTransient The VMX-transient structure.
5630 *
5631 * @remarks No-long-jump zone!!!
5632 */
5633static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5634{
5635 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5636 {
5637 PVM pVM = pVCpu->CTX_SUFF(pVM);
5638 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5639
5640 /*
5641 * Figure out fixed CR0 bits in VMX operation.
5642 */
5643 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5644 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5645 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5646 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5647 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5648 else
5649 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5650
5651 if (!pVmxTransient->fIsNestedGuest)
5652 {
5653 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5654 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5655 uint64_t const u64ShadowCr0 = u64GuestCr0;
5656 Assert(!RT_HI_U32(u64GuestCr0));
5657
5658 /*
5659 * Setup VT-x's view of the guest CR0.
5660 */
5661 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5662 if (pVM->hm.s.fNestedPaging)
5663 {
5664 if (CPUMIsGuestPagingEnabled(pVCpu))
5665 {
5666 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5667 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5668 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5669 }
5670 else
5671 {
5672 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5673 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5674 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5675 }
5676
5677 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5678 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5679 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5680 }
5681 else
5682 {
5683 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5684 u64GuestCr0 |= X86_CR0_WP;
5685 }
5686
5687 /*
5688 * Guest FPU bits.
5689 *
5690 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5691 * using CR0.TS.
5692 *
5693 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5694 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5695 */
5696 u64GuestCr0 |= X86_CR0_NE;
5697
5698 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5699 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5700
5701 /*
5702 * Update exception intercepts.
5703 */
5704 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5705 if (pVmcsInfo->RealMode.fRealOnV86Active)
5706 {
5707 Assert(PDMVmmDevHeapIsEnabled(pVM));
5708 Assert(pVM->hm.s.vmx.pRealModeTSS);
5709 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5710 }
5711 else
5712 {
5713 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5714 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5715 if (fInterceptMF)
5716 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5717 }
5718
5719 /* Additional intercepts for debugging, define these yourself explicitly. */
5720#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5721 uXcptBitmap |= 0
5722 | RT_BIT(X86_XCPT_BP)
5723 | RT_BIT(X86_XCPT_DE)
5724 | RT_BIT(X86_XCPT_NM)
5725 | RT_BIT(X86_XCPT_TS)
5726 | RT_BIT(X86_XCPT_UD)
5727 | RT_BIT(X86_XCPT_NP)
5728 | RT_BIT(X86_XCPT_SS)
5729 | RT_BIT(X86_XCPT_GP)
5730 | RT_BIT(X86_XCPT_PF)
5731 | RT_BIT(X86_XCPT_MF)
5732 ;
5733#elif defined(HMVMX_ALWAYS_TRAP_PF)
5734 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5735#endif
5736 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5737 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5738 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5739
5740 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5741 u64GuestCr0 |= fSetCr0;
5742 u64GuestCr0 &= fZapCr0;
5743 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5744
5745 /* Commit the CR0 and related fields to the guest VMCS. */
5746 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
5747 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5748 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5749 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5750 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5751 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5752 AssertRCReturn(rc, rc);
5753
5754 /* Update our caches. */
5755 pVmcsInfo->u32ProcCtls = uProcCtls;
5756 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5757
5758 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5759 }
5760 else
5761 {
5762 /*
5763 * With nested-guests, we may have extended the guest/host mask here since we
5764 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5765 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5766 * originally supplied. We must copy those bits from the nested-guest CR0 into
5767 * the nested-guest CR0 read-shadow.
5768 */
5769 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5770 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5771 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5772 Assert(!RT_HI_U32(u64GuestCr0));
5773 Assert(u64GuestCr0 & X86_CR0_NE);
5774
5775 /*
5776 * Apply the hardware specified fixed CR0 bits and enable caching.
5777 * Note! We could be altering our VMX emulation's fixed bits. We thus
5778 * need to re-apply them while importing CR0.
5779 */
5780 u64GuestCr0 |= fSetCr0;
5781 u64GuestCr0 &= fZapCr0;
5782 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5783
5784 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5785 /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
5786 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0);
5787 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5788 AssertRCReturn(rc, rc);
5789
5790 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5791 }
5792
5793 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5794 }
5795
5796 return VINF_SUCCESS;
5797}
5798
5799
5800/**
5801 * Exports the guest control registers (CR3, CR4) into the guest-state area
5802 * in the VMCS.
5803 *
5804 * @returns VBox strict status code.
5805 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5806 * without unrestricted guest access and the VMMDev is not presently
5807 * mapped (e.g. EFI32).
5808 *
5809 * @param pVCpu The cross context virtual CPU structure.
5810 * @param pVmxTransient The VMX-transient structure.
5811 *
5812 * @remarks No-long-jump zone!!!
5813 */
5814static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5815{
5816 int rc = VINF_SUCCESS;
5817 PVM pVM = pVCpu->CTX_SUFF(pVM);
5818
5819 /*
5820 * Guest CR2.
5821 * It's always loaded in the assembler code. Nothing to do here.
5822 */
5823
5824 /*
5825 * Guest CR3.
5826 */
5827 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5828 {
5829 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5830
5831 RTGCPHYS GCPhysGuestCr3 = NIL_RTGCPHYS;
5832 if (pVM->hm.s.fNestedPaging)
5833 {
5834 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5835 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5836
5837 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5838 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5839 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5840 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5841
5842 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5843 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5844 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5845
5846 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5847 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5848 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5849 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5850 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5851 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5852 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5853
5854 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5855 AssertRCReturn(rc, rc);
5856
5857 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5858 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5859 || CPUMIsGuestPagingEnabledEx(pCtx))
5860 {
5861 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5862 if (CPUMIsGuestInPAEModeEx(pCtx))
5863 {
5864 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5865 AssertRCReturn(rc, rc);
5866 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
5867 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
5868 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
5869 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
5870 AssertRCReturn(rc, rc);
5871 }
5872
5873 /*
5874 * The guest's view of its CR3 is unblemished with nested paging when the
5875 * guest is using paging or we have unrestricted guest execution to handle
5876 * the guest when it's not using paging.
5877 */
5878 GCPhysGuestCr3 = pCtx->cr3;
5879 }
5880 else
5881 {
5882 /*
5883 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5884 * thinks it accesses physical memory directly, we use our identity-mapped
5885 * page table to map guest-linear to guest-physical addresses. EPT takes care
5886 * of translating it to host-physical addresses.
5887 */
5888 RTGCPHYS GCPhys;
5889 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5890
5891 /* We obtain it here every time as the guest could have relocated this PCI region. */
5892 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5893 if (RT_SUCCESS(rc))
5894 { /* likely */ }
5895 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5896 {
5897 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5898 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5899 }
5900 else
5901 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5902
5903 GCPhysGuestCr3 = GCPhys;
5904 }
5905
5906 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCr3));
5907 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCr3);
5908 AssertRCReturn(rc, rc);
5909 }
5910 else
5911 {
5912 /* Non-nested paging case, just use the hypervisor's CR3. */
5913 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5914
5915 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCr3));
5916 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5917 AssertRCReturn(rc, rc);
5918 }
5919
5920 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5921 }
5922
5923 /*
5924 * Guest CR4.
5925 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5926 */
5927 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5928 {
5929 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5930 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5931
5932 /*
5933 * Figure out fixed CR4 bits in VMX operation.
5934 */
5935 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5936 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5937 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5938
5939 /*
5940 * With nested-guests, we may have extended the guest/host mask here (since we
5941 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5942 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5943 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5944 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5945 */
5946 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5947 uint64_t u64GuestCr4 = pCtx->cr4;
5948 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5949 ? pCtx->cr4
5950 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5951 Assert(!RT_HI_U32(u64GuestCr4));
5952
5953 /*
5954 * Setup VT-x's view of the guest CR4.
5955 *
5956 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5957 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5958 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5959 *
5960 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5961 */
5962 if (pVmcsInfo->RealMode.fRealOnV86Active)
5963 {
5964 Assert(pVM->hm.s.vmx.pRealModeTSS);
5965 Assert(PDMVmmDevHeapIsEnabled(pVM));
5966 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5967 }
5968
5969 if (pVM->hm.s.fNestedPaging)
5970 {
5971 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5972 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5973 {
5974 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5975 u64GuestCr4 |= X86_CR4_PSE;
5976 /* Our identity mapping is a 32-bit page directory. */
5977 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5978 }
5979 /* else use guest CR4.*/
5980 }
5981 else
5982 {
5983 Assert(!pVmxTransient->fIsNestedGuest);
5984
5985 /*
5986 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5987 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5988 */
5989 switch (pVCpu->hm.s.enmShadowMode)
5990 {
5991 case PGMMODE_REAL: /* Real-mode. */
5992 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5993 case PGMMODE_32_BIT: /* 32-bit paging. */
5994 {
5995 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5996 break;
5997 }
5998
5999 case PGMMODE_PAE: /* PAE paging. */
6000 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6001 {
6002 u64GuestCr4 |= X86_CR4_PAE;
6003 break;
6004 }
6005
6006 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6007 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6008#ifdef VBOX_ENABLE_64_BITS_GUESTS
6009 break;
6010#endif
6011 default:
6012 AssertFailed();
6013 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6014 }
6015 }
6016
6017 /*
6018 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
6019 * Note! For nested-guests, we could be altering our VMX emulation's
6020 * fixed bits. We thus need to re-apply them while importing CR4.
6021 */
6022 u64GuestCr4 |= fSetCr4;
6023 u64GuestCr4 &= fZapCr4;
6024
6025 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6026 /** @todo Fix to 64-bit when we drop 32-bit. */
6027 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4);
6028 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
6029 AssertRCReturn(rc, rc);
6030
6031 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6032 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6033
6034 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6035
6036 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6037 }
6038 return rc;
6039}
6040
6041
6042/**
6043 * Exports the guest debug registers into the guest-state area in the VMCS.
6044 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6045 *
6046 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6047 *
6048 * @returns VBox status code.
6049 * @param pVCpu The cross context virtual CPU structure.
6050 * @param pVmxTransient The VMX-transient structure.
6051 *
6052 * @remarks No-long-jump zone!!!
6053 */
6054static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6055{
6056 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6057
6058 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6059 * stepping. */
6060 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6061 if (pVmxTransient->fIsNestedGuest)
6062 {
6063 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6064 AssertRCReturn(rc, rc);
6065 return VINF_SUCCESS;
6066 }
6067
6068#ifdef VBOX_STRICT
6069 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6070 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6071 {
6072 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6073 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6074 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6075 }
6076#endif
6077
6078 bool fSteppingDB = false;
6079 bool fInterceptMovDRx = false;
6080 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6081 if (pVCpu->hm.s.fSingleInstruction)
6082 {
6083 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6084 PVM pVM = pVCpu->CTX_SUFF(pVM);
6085 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6086 {
6087 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6088 Assert(fSteppingDB == false);
6089 }
6090 else
6091 {
6092 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6093 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6094 pVCpu->hm.s.fClearTrapFlag = true;
6095 fSteppingDB = true;
6096 }
6097 }
6098
6099 uint32_t u32GuestDr7;
6100 if ( fSteppingDB
6101 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6102 {
6103 /*
6104 * Use the combined guest and host DRx values found in the hypervisor register set
6105 * because the hypervisor debugger has breakpoints active or someone is single stepping
6106 * on the host side without a monitor trap flag.
6107 *
6108 * Note! DBGF expects a clean DR6 state before executing guest code.
6109 */
6110#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6111 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6112 && !CPUMIsHyperDebugStateActivePending(pVCpu))
6113 {
6114 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6115 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
6116 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
6117 }
6118 else
6119#endif
6120 if (!CPUMIsHyperDebugStateActive(pVCpu))
6121 {
6122 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6123 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6124 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6125 }
6126
6127 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6128 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
6129 pVCpu->hm.s.fUsingHyperDR7 = true;
6130 fInterceptMovDRx = true;
6131 }
6132 else
6133 {
6134 /*
6135 * If the guest has enabled debug registers, we need to load them prior to
6136 * executing guest code so they'll trigger at the right time.
6137 */
6138 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6139 {
6140#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6141 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6142 && !CPUMIsGuestDebugStateActivePending(pVCpu))
6143 {
6144 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6145 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
6146 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
6147 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6148 }
6149 else
6150#endif
6151 if (!CPUMIsGuestDebugStateActive(pVCpu))
6152 {
6153 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6154 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6155 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6156 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6157 }
6158 Assert(!fInterceptMovDRx);
6159 }
6160 /*
6161 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6162 * must intercept #DB in order to maintain a correct DR6 guest value, and
6163 * because we need to intercept it to prevent nested #DBs from hanging the
6164 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6165 */
6166#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6167 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
6168 && !CPUMIsGuestDebugStateActive(pVCpu))
6169#else
6170 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6171#endif
6172 {
6173 fInterceptMovDRx = true;
6174 }
6175
6176 /* Update DR7 with the actual guest value. */
6177 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6178 pVCpu->hm.s.fUsingHyperDR7 = false;
6179 }
6180
6181 if (fInterceptMovDRx)
6182 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6183 else
6184 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6185
6186 /*
6187 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6188 * monitor-trap flag and update our cache.
6189 */
6190 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6191 {
6192 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6193 AssertRCReturn(rc2, rc2);
6194 pVmcsInfo->u32ProcCtls = uProcCtls;
6195 }
6196
6197 /*
6198 * Update guest DR7.
6199 */
6200 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
6201 AssertRCReturn(rc, rc);
6202
6203 /*
6204 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6205 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6206 *
6207 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6208 */
6209 if (fSteppingDB)
6210 {
6211 Assert(pVCpu->hm.s.fSingleInstruction);
6212 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6213
6214 uint32_t fIntrState = 0;
6215 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6216 AssertRCReturn(rc, rc);
6217
6218 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6219 {
6220 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6221 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6222 AssertRCReturn(rc, rc);
6223 }
6224 }
6225
6226 return VINF_SUCCESS;
6227}
6228
6229
6230#ifdef VBOX_STRICT
6231/**
6232 * Strict function to validate segment registers.
6233 *
6234 * @param pVCpu The cross context virtual CPU structure.
6235 * @param pVmcsInfo The VMCS info. object.
6236 *
6237 * @remarks Will import guest CR0 on strict builds during validation of
6238 * segments.
6239 */
6240static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
6241{
6242 /*
6243 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6244 *
6245 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6246 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6247 * unusable bit and doesn't change the guest-context value.
6248 */
6249 PVM pVM = pVCpu->CTX_SUFF(pVM);
6250 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6251 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6252 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6253 && ( !CPUMIsGuestInRealModeEx(pCtx)
6254 && !CPUMIsGuestInV86ModeEx(pCtx)))
6255 {
6256 /* Protected mode checks */
6257 /* CS */
6258 Assert(pCtx->cs.Attr.n.u1Present);
6259 Assert(!(pCtx->cs.Attr.u & 0xf00));
6260 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6261 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6262 || !(pCtx->cs.Attr.n.u1Granularity));
6263 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6264 || (pCtx->cs.Attr.n.u1Granularity));
6265 /* CS cannot be loaded with NULL in protected mode. */
6266 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6267 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6268 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6269 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6270 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6271 else
6272 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6273 /* SS */
6274 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6275 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6276 if ( !(pCtx->cr0 & X86_CR0_PE)
6277 || pCtx->cs.Attr.n.u4Type == 3)
6278 {
6279 Assert(!pCtx->ss.Attr.n.u2Dpl);
6280 }
6281 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6282 {
6283 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6284 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6285 Assert(pCtx->ss.Attr.n.u1Present);
6286 Assert(!(pCtx->ss.Attr.u & 0xf00));
6287 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6288 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6289 || !(pCtx->ss.Attr.n.u1Granularity));
6290 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6291 || (pCtx->ss.Attr.n.u1Granularity));
6292 }
6293 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6294 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6295 {
6296 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6297 Assert(pCtx->ds.Attr.n.u1Present);
6298 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6299 Assert(!(pCtx->ds.Attr.u & 0xf00));
6300 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6301 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6302 || !(pCtx->ds.Attr.n.u1Granularity));
6303 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6304 || (pCtx->ds.Attr.n.u1Granularity));
6305 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6306 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6307 }
6308 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6309 {
6310 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6311 Assert(pCtx->es.Attr.n.u1Present);
6312 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6313 Assert(!(pCtx->es.Attr.u & 0xf00));
6314 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6315 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6316 || !(pCtx->es.Attr.n.u1Granularity));
6317 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6318 || (pCtx->es.Attr.n.u1Granularity));
6319 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6320 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6321 }
6322 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6323 {
6324 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6325 Assert(pCtx->fs.Attr.n.u1Present);
6326 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6327 Assert(!(pCtx->fs.Attr.u & 0xf00));
6328 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6329 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6330 || !(pCtx->fs.Attr.n.u1Granularity));
6331 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6332 || (pCtx->fs.Attr.n.u1Granularity));
6333 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6334 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6335 }
6336 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6337 {
6338 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6339 Assert(pCtx->gs.Attr.n.u1Present);
6340 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6341 Assert(!(pCtx->gs.Attr.u & 0xf00));
6342 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6343 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6344 || !(pCtx->gs.Attr.n.u1Granularity));
6345 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6346 || (pCtx->gs.Attr.n.u1Granularity));
6347 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6348 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6349 }
6350 /* 64-bit capable CPUs. */
6351# if HC_ARCH_BITS == 64
6352 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6353 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6354 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6355 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6356# endif
6357 }
6358 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6359 || ( CPUMIsGuestInRealModeEx(pCtx)
6360 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6361 {
6362 /* Real and v86 mode checks. */
6363 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6364 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6365 if (pVmcsInfo->RealMode.fRealOnV86Active)
6366 {
6367 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6368 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6369 }
6370 else
6371 {
6372 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6373 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6374 }
6375
6376 /* CS */
6377 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6378 Assert(pCtx->cs.u32Limit == 0xffff);
6379 Assert(u32CSAttr == 0xf3);
6380 /* SS */
6381 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6382 Assert(pCtx->ss.u32Limit == 0xffff);
6383 Assert(u32SSAttr == 0xf3);
6384 /* DS */
6385 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6386 Assert(pCtx->ds.u32Limit == 0xffff);
6387 Assert(u32DSAttr == 0xf3);
6388 /* ES */
6389 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6390 Assert(pCtx->es.u32Limit == 0xffff);
6391 Assert(u32ESAttr == 0xf3);
6392 /* FS */
6393 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6394 Assert(pCtx->fs.u32Limit == 0xffff);
6395 Assert(u32FSAttr == 0xf3);
6396 /* GS */
6397 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6398 Assert(pCtx->gs.u32Limit == 0xffff);
6399 Assert(u32GSAttr == 0xf3);
6400 /* 64-bit capable CPUs. */
6401# if HC_ARCH_BITS == 64
6402 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6403 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6404 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6405 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6406# endif
6407 }
6408}
6409#endif /* VBOX_STRICT */
6410
6411
6412/**
6413 * Exports a guest segment register into the guest-state area in the VMCS.
6414 *
6415 * @returns VBox status code.
6416 * @param pVCpu The cross context virtual CPU structure.
6417 * @param pVmcsInfo The VMCS info. object.
6418 * @param iSegReg The segment register number (X86_SREG_XXX).
6419 * @param pSelReg Pointer to the segment selector.
6420 *
6421 * @remarks No-long-jump zone!!!
6422 */
6423static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6424{
6425 Assert(iSegReg < X86_SREG_COUNT);
6426 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6427 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6428 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6429 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6430
6431 uint32_t u32Access = pSelReg->Attr.u;
6432 if (pVmcsInfo->RealMode.fRealOnV86Active)
6433 {
6434 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6435 u32Access = 0xf3;
6436 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6437 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6438 RT_NOREF_PV(pVCpu);
6439 }
6440 else
6441 {
6442 /*
6443 * The way to differentiate between whether this is really a null selector or was just
6444 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6445 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6446 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6447 * NULL selectors loaded in protected-mode have their attribute as 0.
6448 */
6449 if (!u32Access)
6450 u32Access = X86DESCATTR_UNUSABLE;
6451 }
6452
6453 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6454 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6455 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6456
6457 /*
6458 * Commit it to the VMCS.
6459 */
6460 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
6461 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
6462 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
6463 rc |= VMXWriteVmcs32(idxAttr, u32Access);
6464 AssertRCReturn(rc, rc);
6465 return rc;
6466}
6467
6468
6469/**
6470 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6471 * area in the VMCS.
6472 *
6473 * @returns VBox status code.
6474 * @param pVCpu The cross context virtual CPU structure.
6475 * @param pVmxTransient The VMX-transient structure.
6476 *
6477 * @remarks Will import guest CR0 on strict builds during validation of
6478 * segments.
6479 * @remarks No-long-jump zone!!!
6480 */
6481static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6482{
6483 int rc = VERR_INTERNAL_ERROR_5;
6484 PVM pVM = pVCpu->CTX_SUFF(pVM);
6485 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6486 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6487
6488 /*
6489 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6490 */
6491 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6492 {
6493#ifdef VBOX_WITH_REM
6494 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6495 {
6496 Assert(!pVmxTransient->fIsNestedGuest);
6497 Assert(pVM->hm.s.vmx.pRealModeTSS);
6498 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6499 if ( pVmcsInfo->fWasInRealMode
6500 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6501 {
6502 /*
6503 * Notify the recompiler must flush its code-cache as the guest -may-
6504 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6505 */
6506 REMFlushTBs(pVM);
6507 Log4Func(("Switch to protected mode detected!\n"));
6508 pVmcsInfo->fWasInRealMode = false;
6509 }
6510 }
6511#endif
6512 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6513 {
6514 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6515 if (pVmcsInfo->RealMode.fRealOnV86Active)
6516 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6517 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6518 AssertRCReturn(rc, rc);
6519 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6520 }
6521
6522 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6523 {
6524 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6525 if (pVmcsInfo->RealMode.fRealOnV86Active)
6526 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6527 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6528 AssertRCReturn(rc, rc);
6529 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6530 }
6531
6532 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6533 {
6534 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6535 if (pVmcsInfo->RealMode.fRealOnV86Active)
6536 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6537 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6538 AssertRCReturn(rc, rc);
6539 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6540 }
6541
6542 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6543 {
6544 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6545 if (pVmcsInfo->RealMode.fRealOnV86Active)
6546 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6547 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6548 AssertRCReturn(rc, rc);
6549 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6550 }
6551
6552 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6553 {
6554 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6555 if (pVmcsInfo->RealMode.fRealOnV86Active)
6556 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6557 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6558 AssertRCReturn(rc, rc);
6559 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6560 }
6561
6562 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6563 {
6564 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6565 if (pVmcsInfo->RealMode.fRealOnV86Active)
6566 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6567 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6568 AssertRCReturn(rc, rc);
6569 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6570 }
6571
6572#ifdef VBOX_STRICT
6573 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6574#endif
6575 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6576 pCtx->cs.Attr.u));
6577 }
6578
6579 /*
6580 * Guest TR.
6581 */
6582 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6583 {
6584 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6585
6586 /*
6587 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6588 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6589 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6590 */
6591 uint16_t u16Sel;
6592 uint32_t u32Limit;
6593 uint64_t u64Base;
6594 uint32_t u32AccessRights;
6595 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6596 {
6597 u16Sel = pCtx->tr.Sel;
6598 u32Limit = pCtx->tr.u32Limit;
6599 u64Base = pCtx->tr.u64Base;
6600 u32AccessRights = pCtx->tr.Attr.u;
6601 }
6602 else
6603 {
6604 Assert(!pVmxTransient->fIsNestedGuest);
6605 Assert(pVM->hm.s.vmx.pRealModeTSS);
6606 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6607
6608 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6609 RTGCPHYS GCPhys;
6610 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6611 AssertRCReturn(rc, rc);
6612
6613 X86DESCATTR DescAttr;
6614 DescAttr.u = 0;
6615 DescAttr.n.u1Present = 1;
6616 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6617
6618 u16Sel = 0;
6619 u32Limit = HM_VTX_TSS_SIZE;
6620 u64Base = GCPhys;
6621 u32AccessRights = DescAttr.u;
6622 }
6623
6624 /* Validate. */
6625 Assert(!(u16Sel & RT_BIT(2)));
6626 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6627 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6628 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6629 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6630 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6631 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6632 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6633 Assert( (u32Limit & 0xfff) == 0xfff
6634 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6635 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6636 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6637
6638 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
6639 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
6640 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
6641 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
6642 AssertRCReturn(rc, rc);
6643
6644 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6645 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6646 }
6647
6648 /*
6649 * Guest GDTR.
6650 */
6651 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6652 {
6653 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6654
6655 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
6656 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
6657 AssertRCReturn(rc, rc);
6658
6659 /* Validate. */
6660 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6661
6662 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6663 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6664 }
6665
6666 /*
6667 * Guest LDTR.
6668 */
6669 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6670 {
6671 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6672
6673 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6674 uint32_t u32Access;
6675 if ( !pVmxTransient->fIsNestedGuest
6676 && !pCtx->ldtr.Attr.u)
6677 u32Access = X86DESCATTR_UNUSABLE;
6678 else
6679 u32Access = pCtx->ldtr.Attr.u;
6680
6681 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
6682 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
6683 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
6684 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
6685 AssertRCReturn(rc, rc);
6686
6687 /* Validate. */
6688 if (!(u32Access & X86DESCATTR_UNUSABLE))
6689 {
6690 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6691 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6692 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6693 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6694 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6695 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6696 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6697 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6698 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6699 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6700 }
6701
6702 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6703 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6704 }
6705
6706 /*
6707 * Guest IDTR.
6708 */
6709 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6710 {
6711 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6712
6713 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
6714 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
6715 AssertRCReturn(rc, rc);
6716
6717 /* Validate. */
6718 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6719
6720 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6721 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6722 }
6723
6724 return VINF_SUCCESS;
6725}
6726
6727
6728/**
6729 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6730 * areas.
6731 *
6732 * These MSRs will automatically be loaded to the host CPU on every successful
6733 * VM-entry and stored from the host CPU on every successful VM-exit.
6734 *
6735 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6736 * actual host MSR values are not- updated here for performance reasons. See
6737 * hmR0VmxExportHostMsrs().
6738 *
6739 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6740 *
6741 * @returns VBox status code.
6742 * @param pVCpu The cross context virtual CPU structure.
6743 * @param pVmxTransient The VMX-transient structure.
6744 *
6745 * @remarks No-long-jump zone!!!
6746 */
6747static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6748{
6749 AssertPtr(pVCpu);
6750 AssertPtr(pVmxTransient);
6751
6752 PVM pVM = pVCpu->CTX_SUFF(pVM);
6753 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6754
6755 /*
6756 * MSRs that we use the auto-load/store MSR area in the VMCS.
6757 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
6758 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
6759 *
6760 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6761 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6762 * emulation, nothing to do here.
6763 */
6764 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6765 {
6766 if ( !pVmxTransient->fIsNestedGuest
6767 && pVM->hm.s.fAllow64BitGuests)
6768 {
6769#if HC_ARCH_BITS == 32
6770 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
6771 Assert(!pVmxTransient->fIsNestedGuest);
6772
6773 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
6774 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
6775 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
6776 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
6777 AssertRCReturn(rc, rc);
6778#endif
6779 }
6780 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6781 }
6782
6783 /*
6784 * Guest Sysenter MSRs.
6785 */
6786 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6787 {
6788 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6789
6790 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6791 {
6792 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6793 AssertRCReturn(rc, rc);
6794 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6795 }
6796
6797 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6798 {
6799 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6800 AssertRCReturn(rc, rc);
6801 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6802 }
6803
6804 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6805 {
6806 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6807 AssertRCReturn(rc, rc);
6808 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6809 }
6810 }
6811
6812 /*
6813 * Guest/host EFER MSR.
6814 */
6815 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6816 {
6817 /* Whether we are using the VMCS to swap the EFER MSR must have been
6818 determined earlier while exporting VM-entry/VM-exit controls. */
6819 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6820 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6821
6822 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6823 {
6824 /*
6825 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6826 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6827 */
6828 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6829 {
6830 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6831 AssertRCReturn(rc, rc);
6832 }
6833 else
6834 {
6835 /*
6836 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6837 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6838 */
6839 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6840 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6841 AssertRCReturn(rc, rc);
6842 }
6843 }
6844 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6845 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6846
6847 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6848 }
6849
6850 /*
6851 * Other MSRs.
6852 * Speculation Control (R/W).
6853 */
6854 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6855 {
6856 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6857 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6858 {
6859 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6860 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6861 AssertRCReturn(rc, rc);
6862 }
6863 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6864 }
6865
6866 return VINF_SUCCESS;
6867}
6868
6869
6870/**
6871 * Selects up the appropriate function to run guest code.
6872 *
6873 * @returns VBox status code.
6874 * @param pVCpu The cross context virtual CPU structure.
6875 * @param pVmxTransient The VMX-transient structure.
6876 *
6877 * @remarks No-long-jump zone!!!
6878 */
6879static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6880{
6881 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6882 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6883
6884 if (CPUMIsGuestInLongModeEx(pCtx))
6885 {
6886#ifndef VBOX_ENABLE_64_BITS_GUESTS
6887 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6888#endif
6889 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6890#if HC_ARCH_BITS == 32
6891 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
6892 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
6893 {
6894#ifdef VBOX_STRICT
6895 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6896 {
6897 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6898 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6899 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6900 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6901 ("fCtxChanged=%#RX64\n", fCtxChanged));
6902 }
6903#endif
6904 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
6905
6906 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
6907 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
6908 pVmcsInfo->fSwitchedTo64on32 = true;
6909 Log4Func(("Selected 64-bit switcher\n"));
6910 }
6911#else
6912 /* 64-bit host. */
6913 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6914#endif
6915 }
6916 else
6917 {
6918 /* Guest is not in long mode, use the 32-bit handler. */
6919#if HC_ARCH_BITS == 32
6920 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
6921 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
6922 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6923 {
6924# ifdef VBOX_STRICT
6925 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6926 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6927 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6928 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6929 ("fCtxChanged=%#RX64\n", fCtxChanged));
6930# endif
6931 }
6932# ifdef VBOX_ENABLE_64_BITS_GUESTS
6933 /*
6934 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
6935 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
6936 * switcher flag now because we know the guest is in a sane state where it's safe
6937 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
6938 * the much faster 32-bit switcher again.
6939 */
6940 if (!pVmcsInfo->fSwitchedTo64on32)
6941 {
6942 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
6943 Log4Func(("Selected 32-bit switcher\n"));
6944 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6945 }
6946 else
6947 {
6948 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
6949 if ( pVmcsInfo->RealMode.fRealOnV86Active
6950 || hmR0VmxIs32BitSwitcherSafe(pCtx))
6951 {
6952 pVmcsInfo->fSwitchedTo64on32 = false;
6953 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
6955 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
6956 | HM_CHANGED_HOST_CONTEXT);
6957 Log4Func(("Selected 32-bit switcher (safe)\n"));
6958 }
6959 }
6960# else
6961 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6962# endif
6963#else
6964 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6965#endif
6966 }
6967 Assert(pVmcsInfo->pfnStartVM);
6968 return VINF_SUCCESS;
6969}
6970
6971
6972/**
6973 * Wrapper for running the guest code in VT-x.
6974 *
6975 * @returns VBox status code, no informational status codes.
6976 * @param pVCpu The cross context virtual CPU structure.
6977 * @param pVmxTransient The VMX-transient structure.
6978 *
6979 * @remarks No-long-jump zone!!!
6980 */
6981DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
6982{
6983 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6984 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6985 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6986
6987 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6988
6989 /*
6990 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6991 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6992 * callee-saved and thus the need for this XMM wrapper.
6993 *
6994 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6995 */
6996 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6997 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6998 PVM pVM = pVCpu->CTX_SUFF(pVM);
6999#ifdef VBOX_WITH_KERNEL_USING_XMM
7000 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
7001#else
7002 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
7003#endif
7004 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
7005 return rc;
7006}
7007
7008
7009/**
7010 * Reports world-switch error and dumps some useful debug info.
7011 *
7012 * @param pVCpu The cross context virtual CPU structure.
7013 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
7014 * @param pVmxTransient The VMX-transient structure (only
7015 * exitReason updated).
7016 */
7017static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
7018{
7019 Assert(pVCpu);
7020 Assert(pVmxTransient);
7021 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
7022
7023 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
7024 switch (rcVMRun)
7025 {
7026 case VERR_VMX_INVALID_VMXON_PTR:
7027 AssertFailed();
7028 break;
7029 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
7030 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
7031 {
7032 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
7033 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
7034 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
7035 AssertRC(rc);
7036
7037 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
7038 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
7039 Cannot do it here as we may have been long preempted. */
7040
7041#ifdef VBOX_STRICT
7042 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7043 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
7044 pVmxTransient->uExitReason));
7045 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
7046 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
7047 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
7048 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
7049 else
7050 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
7051 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
7052 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
7053
7054 /* VMX control bits. */
7055 uint32_t u32Val;
7056 uint64_t u64Val;
7057 RTHCUINTREG uHCReg;
7058 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
7059 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
7060 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
7061 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
7062 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
7063 {
7064 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
7065 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
7066 }
7067 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
7068 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
7069 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
7070 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
7071 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
7072 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
7073 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
7074 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
7075 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
7076 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
7077 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
7078 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
7079 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
7080 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
7081 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
7082 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
7083 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7084 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
7085 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7086 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
7087 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
7088 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
7089 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
7090 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
7091 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
7092 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
7093 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
7094 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
7095 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
7096 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7097 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
7098 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
7099 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
7100 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7101 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7102 {
7103 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
7104 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
7105 }
7106
7107 /* Guest bits. */
7108 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
7109 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
7110 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
7111 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
7112 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
7113 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
7114 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
7115 {
7116 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
7117 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
7118 }
7119
7120 /* Host bits. */
7121 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
7122 Log4(("Host CR0 %#RHr\n", uHCReg));
7123 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
7124 Log4(("Host CR3 %#RHr\n", uHCReg));
7125 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
7126 Log4(("Host CR4 %#RHr\n", uHCReg));
7127
7128 RTGDTR HostGdtr;
7129 PCX86DESCHC pDesc;
7130 ASMGetGDTR(&HostGdtr);
7131 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
7132 Log4(("Host CS %#08x\n", u32Val));
7133 if (u32Val < HostGdtr.cbGdt)
7134 {
7135 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7136 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
7137 }
7138
7139 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
7140 Log4(("Host DS %#08x\n", u32Val));
7141 if (u32Val < HostGdtr.cbGdt)
7142 {
7143 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7144 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
7145 }
7146
7147 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
7148 Log4(("Host ES %#08x\n", u32Val));
7149 if (u32Val < HostGdtr.cbGdt)
7150 {
7151 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7152 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
7153 }
7154
7155 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
7156 Log4(("Host FS %#08x\n", u32Val));
7157 if (u32Val < HostGdtr.cbGdt)
7158 {
7159 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7160 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
7161 }
7162
7163 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
7164 Log4(("Host GS %#08x\n", u32Val));
7165 if (u32Val < HostGdtr.cbGdt)
7166 {
7167 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7168 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
7169 }
7170
7171 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
7172 Log4(("Host SS %#08x\n", u32Val));
7173 if (u32Val < HostGdtr.cbGdt)
7174 {
7175 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7176 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
7177 }
7178
7179 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
7180 Log4(("Host TR %#08x\n", u32Val));
7181 if (u32Val < HostGdtr.cbGdt)
7182 {
7183 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7184 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
7185 }
7186
7187 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
7188 Log4(("Host TR Base %#RHv\n", uHCReg));
7189 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
7190 Log4(("Host GDTR Base %#RHv\n", uHCReg));
7191 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
7192 Log4(("Host IDTR Base %#RHv\n", uHCReg));
7193 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
7194 Log4(("Host SYSENTER CS %#08x\n", u32Val));
7195 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
7196 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
7197 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
7198 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
7199 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
7200 Log4(("Host RSP %#RHv\n", uHCReg));
7201 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
7202 Log4(("Host RIP %#RHv\n", uHCReg));
7203# if HC_ARCH_BITS == 64
7204 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7205 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7206 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7207 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7208 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7209 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7210# endif
7211#endif /* VBOX_STRICT */
7212 break;
7213 }
7214
7215 default:
7216 /* Impossible */
7217 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7218 break;
7219 }
7220}
7221
7222
7223#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
7224# ifndef VMX_USE_CACHED_VMCS_ACCESSES
7225# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
7226# endif
7227
7228/**
7229 * Initialize the VMCS-Read cache.
7230 *
7231 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
7232 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
7233 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
7234 * (those that have a 32-bit FULL & HIGH part).
7235 *
7236 * @param pVCpu The cross context virtual CPU structure.
7237 */
7238static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
7239{
7240#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
7241 do { \
7242 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
7243 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
7244 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
7245 ++cReadFields; \
7246 } while (0)
7247
7248 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7249 uint32_t cReadFields = 0;
7250
7251 /*
7252 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
7253 * and serve to indicate exceptions to the rules.
7254 */
7255
7256 /* Guest-natural selector base fields. */
7257#if 0
7258 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
7259 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
7260 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
7261#endif
7262 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
7263 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
7264 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
7265 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
7266 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
7267 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
7268 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
7269 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
7270 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
7271 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
7272 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
7273 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
7274#if 0
7275 /* Unused natural width guest-state fields. */
7276 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
7277 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
7278#endif
7279 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
7280 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
7281
7282 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
7283 these 64-bit fields (using "FULL" and "HIGH" fields). */
7284#if 0
7285 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
7286 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
7287 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
7288 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
7289 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
7290 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
7291 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
7292 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
7293 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
7294#endif
7295
7296 /* Natural width guest-state fields. */
7297 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
7298 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
7299
7300 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7301 {
7302 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
7303 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
7304 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
7305 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
7306 }
7307 else
7308 {
7309 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
7310 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
7311 }
7312
7313#undef VMXLOCAL_INIT_READ_CACHE_FIELD
7314}
7315
7316
7317/**
7318 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
7319 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
7320 * darwin, running 64-bit guests).
7321 *
7322 * @returns VBox status code.
7323 * @param pVCpu The cross context virtual CPU structure.
7324 * @param idxField The VMCS field encoding.
7325 * @param u64Val 16, 32 or 64-bit value.
7326 */
7327VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7328{
7329 AssertPtr(pVCpu);
7330 int rc;
7331 switch (idxField)
7332 {
7333 /*
7334 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
7335 */
7336 /* 64-bit Control fields. */
7337 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
7338 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
7339 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
7340 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
7341 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
7342 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
7343 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
7344 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
7345 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
7346 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
7347 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
7348 case VMX_VMCS64_CTRL_EPTP_FULL:
7349 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
7350 /* 64-bit Guest-state fields. */
7351 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
7352 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
7353 case VMX_VMCS64_GUEST_PAT_FULL:
7354 case VMX_VMCS64_GUEST_EFER_FULL:
7355 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
7356 case VMX_VMCS64_GUEST_PDPTE0_FULL:
7357 case VMX_VMCS64_GUEST_PDPTE1_FULL:
7358 case VMX_VMCS64_GUEST_PDPTE2_FULL:
7359 case VMX_VMCS64_GUEST_PDPTE3_FULL:
7360 /* 64-bit Host-state fields. */
7361 case VMX_VMCS64_HOST_PAT_FULL:
7362 case VMX_VMCS64_HOST_EFER_FULL:
7363 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
7364 {
7365 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7366 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
7367 break;
7368 }
7369
7370 /*
7371 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
7372 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
7373 */
7374 /* Natural-width Guest-state fields. */
7375 case VMX_VMCS_GUEST_CR3:
7376 case VMX_VMCS_GUEST_ES_BASE:
7377 case VMX_VMCS_GUEST_CS_BASE:
7378 case VMX_VMCS_GUEST_SS_BASE:
7379 case VMX_VMCS_GUEST_DS_BASE:
7380 case VMX_VMCS_GUEST_FS_BASE:
7381 case VMX_VMCS_GUEST_GS_BASE:
7382 case VMX_VMCS_GUEST_LDTR_BASE:
7383 case VMX_VMCS_GUEST_TR_BASE:
7384 case VMX_VMCS_GUEST_GDTR_BASE:
7385 case VMX_VMCS_GUEST_IDTR_BASE:
7386 case VMX_VMCS_GUEST_RSP:
7387 case VMX_VMCS_GUEST_RIP:
7388 case VMX_VMCS_GUEST_SYSENTER_ESP:
7389 case VMX_VMCS_GUEST_SYSENTER_EIP:
7390 {
7391 if (!(RT_HI_U32(u64Val)))
7392 {
7393 /* If this field is 64-bit, VT-x will zero out the top bits. */
7394 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7395 }
7396 else
7397 {
7398 /* Assert that only the 32->64 switcher case should ever come here. */
7399 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
7400 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
7401 }
7402 break;
7403 }
7404
7405 default:
7406 {
7407 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
7408 pVCpu->hm.s.u32HMError = idxField;
7409 rc = VERR_INVALID_PARAMETER;
7410 break;
7411 }
7412 }
7413 AssertRCReturn(rc, rc);
7414 return rc;
7415}
7416
7417
7418/**
7419 * Queue up a VMWRITE by using the VMCS write cache.
7420 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
7421 *
7422 * @param pVCpu The cross context virtual CPU structure.
7423 * @param idxField The VMCS field encoding.
7424 * @param u64Val 16, 32 or 64-bit value.
7425 */
7426VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7427{
7428 AssertPtr(pVCpu);
7429 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7430
7431 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
7432 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
7433
7434 /* Make sure there are no duplicates. */
7435 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
7436 {
7437 if (pCache->Write.aField[i] == idxField)
7438 {
7439 pCache->Write.aFieldVal[i] = u64Val;
7440 return VINF_SUCCESS;
7441 }
7442 }
7443
7444 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
7445 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
7446 pCache->Write.cValidEntries++;
7447 return VINF_SUCCESS;
7448}
7449#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
7450
7451
7452/**
7453 * Sets up the usage of TSC-offsetting and updates the VMCS.
7454 *
7455 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7456 * VMX-preemption timer.
7457 *
7458 * @returns VBox status code.
7459 * @param pVCpu The cross context virtual CPU structure.
7460 * @param pVmxTransient The VMX-transient structure.
7461 *
7462 * @remarks No-long-jump zone!!!
7463 */
7464static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
7465{
7466 bool fOffsettedTsc;
7467 bool fParavirtTsc;
7468 uint64_t uTscOffset;
7469 PVM pVM = pVCpu->CTX_SUFF(pVM);
7470 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7471
7472 if (pVM->hm.s.vmx.fUsePreemptTimer)
7473 {
7474 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7475
7476 /* Make sure the returned values have sane upper and lower boundaries. */
7477 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7478 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7479 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7480 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7481
7482 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7483 * preemption timers here. We probably need to clamp the preemption timer,
7484 * after converting the timer value to the host. */
7485 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7486 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7487 AssertRC(rc);
7488 }
7489 else
7490 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7491
7492 if (fParavirtTsc)
7493 {
7494 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7495 information before every VM-entry, hence disable it for performance sake. */
7496#if 0
7497 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7498 AssertRC(rc);
7499#endif
7500 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7501 }
7502
7503 if ( fOffsettedTsc
7504 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7505 {
7506 if (pVmxTransient->fIsNestedGuest)
7507 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7508 hmR0VmxSetTscOffsetVmcs(pVCpu, pVmcsInfo, uTscOffset);
7509 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7510 }
7511 else
7512 {
7513 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7514 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7515 }
7516}
7517
7518
7519/**
7520 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7521 * VM-exit interruption info type.
7522 *
7523 * @returns The IEM exception flags.
7524 * @param uVector The event vector.
7525 * @param uVmxEventType The VMX event type.
7526 *
7527 * @remarks This function currently only constructs flags required for
7528 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7529 * and CR2 aspects of an exception are not included).
7530 */
7531static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7532{
7533 uint32_t fIemXcptFlags;
7534 switch (uVmxEventType)
7535 {
7536 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7537 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7538 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7539 break;
7540
7541 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7542 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7543 break;
7544
7545 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7546 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7547 break;
7548
7549 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7550 {
7551 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7552 if (uVector == X86_XCPT_BP)
7553 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7554 else if (uVector == X86_XCPT_OF)
7555 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7556 else
7557 {
7558 fIemXcptFlags = 0;
7559 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7560 }
7561 break;
7562 }
7563
7564 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7565 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7566 break;
7567
7568 default:
7569 fIemXcptFlags = 0;
7570 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7571 break;
7572 }
7573 return fIemXcptFlags;
7574}
7575
7576
7577/**
7578 * Sets an event as a pending event to be injected into the guest.
7579 *
7580 * @param pVCpu The cross context virtual CPU structure.
7581 * @param u32IntInfo The VM-entry interruption-information field.
7582 * @param cbInstr The VM-entry instruction length in bytes (for software
7583 * interrupts, exceptions and privileged software
7584 * exceptions).
7585 * @param u32ErrCode The VM-entry exception error code.
7586 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7587 * page-fault.
7588 */
7589DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7590 RTGCUINTPTR GCPtrFaultAddress)
7591{
7592 Assert(!pVCpu->hm.s.Event.fPending);
7593 pVCpu->hm.s.Event.fPending = true;
7594 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7595 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7596 pVCpu->hm.s.Event.cbInstr = cbInstr;
7597 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7598}
7599
7600
7601/**
7602 * Sets an external interrupt as pending-for-injection into the VM.
7603 *
7604 * @param pVCpu The cross context virtual CPU structure.
7605 * @param u8Interrupt The external interrupt vector.
7606 */
7607DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
7608{
7609 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7610 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7611 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7612 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7613 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7614}
7615
7616
7617/**
7618 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7619 *
7620 * @param pVCpu The cross context virtual CPU structure.
7621 */
7622DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
7623{
7624 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7625 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7626 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7627 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7628 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7629}
7630
7631
7632/**
7633 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7634 *
7635 * @param pVCpu The cross context virtual CPU structure.
7636 */
7637DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
7638{
7639 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7640 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7641 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7642 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7643 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7644}
7645
7646
7647/**
7648 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7649 *
7650 * @param pVCpu The cross context virtual CPU structure.
7651 */
7652DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
7653{
7654 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7655 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7656 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7657 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7658 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7659}
7660
7661
7662/**
7663 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7664 *
7665 * @param pVCpu The cross context virtual CPU structure.
7666 */
7667DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
7668{
7669 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7670 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7671 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7672 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7673 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7674}
7675
7676
7677#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7678/**
7679 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7680 *
7681 * @param pVCpu The cross context virtual CPU structure.
7682 * @param u32ErrCode The error code for the general-protection exception.
7683 */
7684DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
7685{
7686 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7687 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7688 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7689 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7690 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7691}
7692
7693
7694/**
7695 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7696 *
7697 * @param pVCpu The cross context virtual CPU structure.
7698 * @param u32ErrCode The error code for the stack exception.
7699 */
7700DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
7701{
7702 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7703 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7704 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7705 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7706 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7707}
7708#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7709
7710
7711/**
7712 * Fixes up attributes for the specified segment register.
7713 *
7714 * @param pVCpu The cross context virtual CPU structure.
7715 * @param pSelReg The segment register that needs fixing.
7716 * @param idxSel The VMCS field for the corresponding segment register.
7717 */
7718static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7719{
7720 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7721
7722 /*
7723 * If VT-x marks the segment as unusable, most other bits remain undefined:
7724 * - For CS the L, D and G bits have meaning.
7725 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7726 * - For the remaining data segments no bits are defined.
7727 *
7728 * The present bit and the unusable bit has been observed to be set at the
7729 * same time (the selector was supposed to be invalid as we started executing
7730 * a V8086 interrupt in ring-0).
7731 *
7732 * What should be important for the rest of the VBox code, is that the P bit is
7733 * cleared. Some of the other VBox code recognizes the unusable bit, but
7734 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7735 * safe side here, we'll strip off P and other bits we don't care about. If
7736 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7737 *
7738 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7739 */
7740#ifdef VBOX_STRICT
7741 uint32_t const uAttr = pSelReg->Attr.u;
7742#endif
7743
7744 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7745 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7746 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7747
7748#ifdef VBOX_STRICT
7749 VMMRZCallRing3Disable(pVCpu);
7750 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7751# ifdef DEBUG_bird
7752 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7753 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7754 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7755# endif
7756 VMMRZCallRing3Enable(pVCpu);
7757 NOREF(uAttr);
7758#endif
7759 RT_NOREF2(pVCpu, idxSel);
7760}
7761
7762
7763/**
7764 * Imports a guest segment register from the current VMCS into the guest-CPU
7765 * context.
7766 *
7767 * @returns VBox status code.
7768 * @param pVCpu The cross context virtual CPU structure.
7769 * @param iSegReg The segment register number (X86_SREG_XXX).
7770 *
7771 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7772 * do not log!
7773 */
7774static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7775{
7776 Assert(iSegReg < X86_SREG_COUNT);
7777
7778 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7779 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7780 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7781#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7782 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7783#else
7784 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7785#endif
7786 uint64_t u64Base;
7787 uint32_t u32Sel, u32Limit, u32Attr;
7788 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7789 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7790 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7791 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7792 if (RT_SUCCESS(rc))
7793 {
7794 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7795 pSelReg->Sel = u32Sel;
7796 pSelReg->ValidSel = u32Sel;
7797 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7798 pSelReg->u32Limit = u32Limit;
7799 pSelReg->u64Base = u64Base;
7800 pSelReg->Attr.u = u32Attr;
7801 if (u32Attr & X86DESCATTR_UNUSABLE)
7802 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7803 }
7804 return rc;
7805}
7806
7807
7808/**
7809 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7810 *
7811 * @returns VBox status code.
7812 * @param pVCpu The cross context virtual CPU structure.
7813 *
7814 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7815 * do not log!
7816 */
7817static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7818{
7819 uint64_t u64Base;
7820 uint32_t u32Sel, u32Limit, u32Attr;
7821 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7822 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7823 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7824 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7825 if (RT_SUCCESS(rc))
7826 {
7827 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7828 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7829 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7830 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7831 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7832 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7833 if (u32Attr & X86DESCATTR_UNUSABLE)
7834 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7835 }
7836 return rc;
7837}
7838
7839
7840/**
7841 * Imports the guest TR from the current VMCS into the guest-CPU context.
7842 *
7843 * @returns VBox status code.
7844 * @param pVCpu The cross context virtual CPU structure.
7845 *
7846 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7847 * do not log!
7848 */
7849static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7850{
7851 uint32_t u32Sel, u32Limit, u32Attr;
7852 uint64_t u64Base;
7853 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7854 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7855 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7856 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7857 AssertRCReturn(rc, rc);
7858
7859 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7860 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7861 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7862 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7863 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7864 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7865 /* TR is the only selector that can never be unusable. */
7866 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7867 return VINF_SUCCESS;
7868}
7869
7870
7871/**
7872 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7873 *
7874 * @returns VBox status code.
7875 * @param pVCpu The cross context virtual CPU structure.
7876 *
7877 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7878 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7879 * instead!!!
7880 */
7881static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7882{
7883 uint64_t u64Val;
7884 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7885 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7886 {
7887 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7888 if (RT_SUCCESS(rc))
7889 {
7890 pCtx->rip = u64Val;
7891 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7892 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7893 }
7894 return rc;
7895 }
7896 return VINF_SUCCESS;
7897}
7898
7899
7900/**
7901 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7902 *
7903 * @returns VBox status code.
7904 * @param pVCpu The cross context virtual CPU structure.
7905 * @param pVmcsInfo The VMCS info. object.
7906 *
7907 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7908 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7909 * instead!!!
7910 */
7911static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7912{
7913 uint32_t u32Val;
7914 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7915 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7916 {
7917 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7918 if (RT_SUCCESS(rc))
7919 {
7920 pCtx->eflags.u32 = u32Val;
7921
7922 /* Restore eflags for real-on-v86-mode hack. */
7923 if (pVmcsInfo->RealMode.fRealOnV86Active)
7924 {
7925 pCtx->eflags.Bits.u1VM = 0;
7926 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7927 }
7928 }
7929 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7930 return rc;
7931 }
7932 return VINF_SUCCESS;
7933}
7934
7935
7936/**
7937 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7938 * context.
7939 *
7940 * @returns VBox status code.
7941 * @param pVCpu The cross context virtual CPU structure.
7942 * @param pVmcsInfo The VMCS info. object.
7943 *
7944 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7945 * do not log!
7946 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7947 * instead!!!
7948 */
7949static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7950{
7951 uint32_t u32Val;
7952 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
7953 if (RT_SUCCESS(rc))
7954 {
7955 if (!u32Val)
7956 {
7957 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7958 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7959
7960 CPUMSetGuestNmiBlocking(pVCpu, false);
7961 }
7962 else
7963 {
7964 /*
7965 * We must import RIP here to set our EM interrupt-inhibited state.
7966 * We also import RFLAGS as our code that evaluates pending interrupts
7967 * before VM-entry requires it.
7968 */
7969 rc = hmR0VmxImportGuestRip(pVCpu);
7970 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7971 if (RT_SUCCESS(rc))
7972 {
7973 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7974 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7975 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7976 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7977
7978 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7979 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7980 }
7981 }
7982 }
7983 return rc;
7984}
7985
7986
7987/**
7988 * Worker for VMXR0ImportStateOnDemand.
7989 *
7990 * @returns VBox status code.
7991 * @param pVCpu The cross context virtual CPU structure.
7992 * @param pVmcsInfo The VMCS info. object.
7993 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7994 */
7995static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7996{
7997#define VMXLOCAL_BREAK_RC(a_rc) \
7998 if (RT_SUCCESS(a_rc)) \
7999 { } \
8000 else \
8001 break
8002
8003 int rc = VINF_SUCCESS;
8004 PVM pVM = pVCpu->CTX_SUFF(pVM);
8005 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8006 uint64_t u64Val;
8007 uint32_t u32Val;
8008
8009 /*
8010 * Note! This is hack to workaround a mysterious BSOD observed with release builds
8011 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
8012 * neither are other host platforms.
8013 *
8014 * Committing this temporarily as it prevents BSOD.
8015 *
8016 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
8017 */
8018#ifdef RT_OS_WINDOWS
8019 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
8020 return VERR_HM_IPE_1;
8021#endif
8022
8023 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
8024
8025 /*
8026 * We disable interrupts to make the updating of the state and in particular
8027 * the fExtrn modification atomic wrt to preemption hooks.
8028 */
8029 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
8030
8031 fWhat &= pCtx->fExtrn;
8032 if (fWhat)
8033 {
8034 do
8035 {
8036 if (fWhat & CPUMCTX_EXTRN_RIP)
8037 {
8038 rc = hmR0VmxImportGuestRip(pVCpu);
8039 VMXLOCAL_BREAK_RC(rc);
8040 }
8041
8042 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
8043 {
8044 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8045 VMXLOCAL_BREAK_RC(rc);
8046 }
8047
8048 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
8049 {
8050 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
8051 VMXLOCAL_BREAK_RC(rc);
8052 }
8053
8054 if (fWhat & CPUMCTX_EXTRN_RSP)
8055 {
8056 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
8057 VMXLOCAL_BREAK_RC(rc);
8058 pCtx->rsp = u64Val;
8059 }
8060
8061 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
8062 {
8063 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
8064 if (fWhat & CPUMCTX_EXTRN_CS)
8065 {
8066 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
8067 rc |= hmR0VmxImportGuestRip(pVCpu);
8068 if (fRealOnV86Active)
8069 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
8070 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
8071 }
8072 if (fWhat & CPUMCTX_EXTRN_SS)
8073 {
8074 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
8075 if (fRealOnV86Active)
8076 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
8077 }
8078 if (fWhat & CPUMCTX_EXTRN_DS)
8079 {
8080 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
8081 if (fRealOnV86Active)
8082 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
8083 }
8084 if (fWhat & CPUMCTX_EXTRN_ES)
8085 {
8086 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
8087 if (fRealOnV86Active)
8088 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
8089 }
8090 if (fWhat & CPUMCTX_EXTRN_FS)
8091 {
8092 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
8093 if (fRealOnV86Active)
8094 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
8095 }
8096 if (fWhat & CPUMCTX_EXTRN_GS)
8097 {
8098 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
8099 if (fRealOnV86Active)
8100 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
8101 }
8102 VMXLOCAL_BREAK_RC(rc);
8103 }
8104
8105 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
8106 {
8107 if (fWhat & CPUMCTX_EXTRN_LDTR)
8108 rc |= hmR0VmxImportGuestLdtr(pVCpu);
8109
8110 if (fWhat & CPUMCTX_EXTRN_GDTR)
8111 {
8112 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
8113 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
8114 pCtx->gdtr.pGdt = u64Val;
8115 pCtx->gdtr.cbGdt = u32Val;
8116 }
8117
8118 /* Guest IDTR. */
8119 if (fWhat & CPUMCTX_EXTRN_IDTR)
8120 {
8121 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
8122 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
8123 pCtx->idtr.pIdt = u64Val;
8124 pCtx->idtr.cbIdt = u32Val;
8125 }
8126
8127 /* Guest TR. */
8128 if (fWhat & CPUMCTX_EXTRN_TR)
8129 {
8130 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
8131 don't need to import that one. */
8132 if (!pVmcsInfo->RealMode.fRealOnV86Active)
8133 rc |= hmR0VmxImportGuestTr(pVCpu);
8134 }
8135 VMXLOCAL_BREAK_RC(rc);
8136 }
8137
8138 if (fWhat & CPUMCTX_EXTRN_DR7)
8139 {
8140 if (!pVCpu->hm.s.fUsingHyperDR7)
8141 {
8142 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
8143 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
8144 VMXLOCAL_BREAK_RC(rc);
8145 pCtx->dr[7] = u32Val;
8146 }
8147 }
8148
8149 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
8150 {
8151 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
8152 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
8153 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
8154 pCtx->SysEnter.cs = u32Val;
8155 VMXLOCAL_BREAK_RC(rc);
8156 }
8157
8158#if HC_ARCH_BITS == 64
8159 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
8160 {
8161 if ( pVM->hm.s.fAllow64BitGuests
8162 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8163 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
8164 }
8165
8166 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
8167 {
8168 if ( pVM->hm.s.fAllow64BitGuests
8169 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8170 {
8171 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
8172 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
8173 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
8174 }
8175 }
8176#endif
8177
8178 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
8179#if HC_ARCH_BITS == 32
8180 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
8181#endif
8182 )
8183 {
8184 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
8185 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
8186 Assert(pMsrs);
8187 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
8188 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
8189 for (uint32_t i = 0; i < cMsrs; i++)
8190 {
8191 uint32_t const idMsr = pMsrs[i].u32Msr;
8192 switch (idMsr)
8193 {
8194 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
8195 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
8196 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
8197#if HC_ARCH_BITS == 32
8198 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
8199 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
8200 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
8201 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
8202#endif
8203 default:
8204 {
8205 pCtx->fExtrn = 0;
8206 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
8207 ASMSetFlags(fEFlags);
8208 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
8209 return VERR_HM_UNEXPECTED_LD_ST_MSR;
8210 }
8211 }
8212 }
8213 }
8214
8215 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
8216 {
8217 uint64_t u64Shadow;
8218 if (fWhat & CPUMCTX_EXTRN_CR0)
8219 {
8220 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8221 * remove when we drop 32-bit host w/ 64-bit host support, see
8222 * @bugref{9180#c39}. */
8223 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
8224#if HC_ARCH_BITS == 32
8225 uint32_t u32Shadow;
8226 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
8227 u64Shadow = u32Shadow;
8228#else
8229 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
8230#endif
8231 VMXLOCAL_BREAK_RC(rc);
8232 u64Val = u32Val;
8233 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
8234 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
8235#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8236 /*
8237 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
8238 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
8239 */
8240 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8241 {
8242 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
8243 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
8244 }
8245#endif
8246 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
8247 CPUMSetGuestCR0(pVCpu, u64Val);
8248 VMMRZCallRing3Enable(pVCpu);
8249 }
8250
8251 if (fWhat & CPUMCTX_EXTRN_CR4)
8252 {
8253 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8254 * remove when we drop 32-bit host w/ 64-bit host support, see
8255 * @bugref{9180#c39}. */
8256 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
8257#if HC_ARCH_BITS == 32
8258 uint32_t u32Shadow;
8259 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
8260 u64Shadow = u32Shadow;
8261#else
8262 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
8263#endif
8264 VMXLOCAL_BREAK_RC(rc);
8265 u64Val = u32Val;
8266 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
8267 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
8268#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8269 /*
8270 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
8271 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
8272 */
8273 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8274 {
8275 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
8276 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
8277 }
8278#endif
8279 pCtx->cr4 = u64Val;
8280 }
8281
8282 if (fWhat & CPUMCTX_EXTRN_CR3)
8283 {
8284 /* CR0.PG bit changes are always intercepted, so it's up to date. */
8285 if ( pVM->hm.s.vmx.fUnrestrictedGuest
8286 || ( pVM->hm.s.fNestedPaging
8287 && CPUMIsGuestPagingEnabledEx(pCtx)))
8288 {
8289 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
8290 VMXLOCAL_BREAK_RC(rc);
8291 if (pCtx->cr3 != u64Val)
8292 {
8293 pCtx->cr3 = u64Val;
8294 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
8295 }
8296
8297 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
8298 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
8299 if (CPUMIsGuestInPAEModeEx(pCtx))
8300 {
8301 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
8302 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
8303 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
8304 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
8305 VMXLOCAL_BREAK_RC(rc);
8306 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
8307 }
8308 }
8309 }
8310 }
8311
8312#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8313 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
8314 {
8315 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
8316 && !CPUMIsGuestInVmxNonRootMode(pCtx))
8317 {
8318 Assert(CPUMIsGuestInVmxRootMode(pCtx));
8319 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
8320 VMXLOCAL_BREAK_RC(rc);
8321 }
8322 }
8323#endif
8324 } while (0);
8325
8326 if (RT_SUCCESS(rc))
8327 {
8328 /* Update fExtrn. */
8329 pCtx->fExtrn &= ~fWhat;
8330
8331 /* If everything has been imported, clear the HM keeper bit. */
8332 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8333 {
8334 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8335 Assert(!pCtx->fExtrn);
8336 }
8337 }
8338 }
8339 else
8340 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8341
8342 ASMSetFlags(fEFlags);
8343
8344 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8345
8346 if (RT_SUCCESS(rc))
8347 { /* likely */ }
8348 else
8349 return rc;
8350
8351 /*
8352 * Honor any pending CR3 updates.
8353 *
8354 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
8355 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8356 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8357 *
8358 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8359 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8360 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8361 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8362 *
8363 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8364 */
8365 if (VMMRZCallRing3IsEnabled(pVCpu))
8366 {
8367 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8368 {
8369 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8370 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8371 }
8372
8373 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8374 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8375
8376 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8377 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8378 }
8379
8380 return VINF_SUCCESS;
8381#undef VMXLOCAL_BREAK_RC
8382}
8383
8384
8385/**
8386 * Saves the guest state from the VMCS into the guest-CPU context.
8387 *
8388 * @returns VBox status code.
8389 * @param pVCpu The cross context virtual CPU structure.
8390 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8391 */
8392VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
8393{
8394 AssertPtr(pVCpu);
8395 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8396 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8397}
8398
8399
8400/**
8401 * Check per-VM and per-VCPU force flag actions that require us to go back to
8402 * ring-3 for one reason or another.
8403 *
8404 * @returns Strict VBox status code (i.e. informational status codes too)
8405 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8406 * ring-3.
8407 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8408 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8409 * interrupts)
8410 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8411 * all EMTs to be in ring-3.
8412 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8413 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8414 * to the EM loop.
8415 *
8416 * @param pVCpu The cross context virtual CPU structure.
8417 * @param fStepping Whether we are single-stepping the guest using the
8418 * hypervisor debugger.
8419 */
8420static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
8421{
8422 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8423
8424 /*
8425 * Update pending interrupts into the APIC's IRR.
8426 */
8427 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8428 APICUpdatePendingInterrupts(pVCpu);
8429
8430 /*
8431 * Anything pending? Should be more likely than not if we're doing a good job.
8432 */
8433 PVM pVM = pVCpu->CTX_SUFF(pVM);
8434 if ( !fStepping
8435 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8436 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8437 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8438 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8439 return VINF_SUCCESS;
8440
8441 /* Pending PGM C3 sync. */
8442 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8443 {
8444 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8445 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8446 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8447 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8448 if (rcStrict2 != VINF_SUCCESS)
8449 {
8450 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
8451 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
8452 return rcStrict2;
8453 }
8454 }
8455
8456 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8457 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8458 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8459 {
8460 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8461 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8462 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
8463 return rc2;
8464 }
8465
8466 /* Pending VM request packets, such as hardware interrupts. */
8467 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8468 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8469 {
8470 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8471 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8472 return VINF_EM_PENDING_REQUEST;
8473 }
8474
8475 /* Pending PGM pool flushes. */
8476 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8477 {
8478 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8479 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8480 return VINF_PGM_POOL_FLUSH_PENDING;
8481 }
8482
8483 /* Pending DMA requests. */
8484 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8485 {
8486 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8487 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8488 return VINF_EM_RAW_TO_R3;
8489 }
8490
8491 return VINF_SUCCESS;
8492}
8493
8494
8495/**
8496 * Converts any TRPM trap into a pending HM event. This is typically used when
8497 * entering from ring-3 (not longjmp returns).
8498 *
8499 * @param pVCpu The cross context virtual CPU structure.
8500 */
8501static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
8502{
8503 Assert(TRPMHasTrap(pVCpu));
8504 Assert(!pVCpu->hm.s.Event.fPending);
8505
8506 uint8_t uVector;
8507 TRPMEVENT enmTrpmEvent;
8508 RTGCUINT uErrCode;
8509 RTGCUINTPTR GCPtrFaultAddress;
8510 uint8_t cbInstr;
8511
8512 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
8513 AssertRC(rc);
8514
8515 uint32_t u32IntInfo;
8516 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8517 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
8518
8519 rc = TRPMResetTrap(pVCpu);
8520 AssertRC(rc);
8521 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8522 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8523
8524 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8525}
8526
8527
8528/**
8529 * Converts the pending HM event into a TRPM trap.
8530 *
8531 * @param pVCpu The cross context virtual CPU structure.
8532 */
8533static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
8534{
8535 Assert(pVCpu->hm.s.Event.fPending);
8536
8537 /* If a trap was already pending, we did something wrong! */
8538 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8539
8540 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8541 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8542 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8543
8544 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8545
8546 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8547 AssertRC(rc);
8548
8549 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8550 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8551
8552 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8553 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8554 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
8555 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8556
8557 /* We're now done converting the pending event. */
8558 pVCpu->hm.s.Event.fPending = false;
8559}
8560
8561
8562/**
8563 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8564 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8565 *
8566 * @param pVCpu The cross context virtual CPU structure.
8567 * @param pVmcsInfo The VMCS info. object.
8568 */
8569static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8570{
8571 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8572 {
8573 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8574 {
8575 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8576 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8577 AssertRC(rc);
8578 }
8579 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8580}
8581
8582
8583/**
8584 * Clears the interrupt-window exiting control in the VMCS.
8585 *
8586 * @param pVmcsInfo The VMCS info. object.
8587 */
8588DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8589{
8590 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8591 {
8592 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8593 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8594 }
8595 return VINF_SUCCESS;
8596}
8597
8598
8599/**
8600 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8601 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8602 *
8603 * @param pVCpu The cross context virtual CPU structure.
8604 * @param pVmcsInfo The VMCS info. object.
8605 */
8606static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8607{
8608 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8609 {
8610 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8611 {
8612 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8613 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8614 AssertRC(rc);
8615 Log4Func(("Setup NMI-window exiting\n"));
8616 }
8617 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8618}
8619
8620
8621/**
8622 * Clears the NMI-window exiting control in the VMCS.
8623 *
8624 * @param pVmcsInfo The VMCS info. object.
8625 */
8626DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8627{
8628 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8629 {
8630 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8631 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8632 }
8633 return VINF_SUCCESS;
8634}
8635
8636
8637/**
8638 * Does the necessary state syncing before returning to ring-3 for any reason
8639 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8640 *
8641 * @returns VBox status code.
8642 * @param pVCpu The cross context virtual CPU structure.
8643 * @param fImportState Whether to import the guest state from the VMCS back
8644 * to the guest-CPU context.
8645 *
8646 * @remarks No-long-jmp zone!!!
8647 */
8648static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
8649{
8650 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8651 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8652
8653 RTCPUID const idCpu = RTMpCpuId();
8654 Log4Func(("HostCpuId=%u\n", idCpu));
8655
8656 /*
8657 * !!! IMPORTANT !!!
8658 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8659 */
8660
8661 /* Save the guest state if necessary. */
8662 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8663 if (fImportState)
8664 {
8665 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8666 AssertRCReturn(rc, rc);
8667 }
8668
8669 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8670 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8671 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8672
8673 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8674#ifdef VBOX_STRICT
8675 if (CPUMIsHyperDebugStateActive(pVCpu))
8676 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8677#endif
8678 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8679 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8680 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8681
8682#if HC_ARCH_BITS == 64
8683 /* Restore host-state bits that VT-x only restores partially. */
8684 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8685 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8686 {
8687 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8688 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8689 }
8690 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8691#endif
8692
8693 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8694 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8695 {
8696 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8697 if (!fImportState)
8698 {
8699 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8700 AssertRCReturn(rc, rc);
8701 }
8702 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8703 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8704 }
8705 else
8706 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8707
8708 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8709 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8710
8711 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8712 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8713 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8714 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8715 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8716 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8717 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8718 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8719 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8720 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8721
8722 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8723
8724 /** @todo This partially defeats the purpose of having preemption hooks.
8725 * The problem is, deregistering the hooks should be moved to a place that
8726 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8727 * context.
8728 */
8729 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8730 AssertRCReturn(rc, rc);
8731
8732#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8733 /*
8734 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8735 * clear a shadow VMCS before allowing that VMCS to become active on another
8736 * logical processor. We may or may not be importing guest state which clears
8737 * it, so cover for it here.
8738 *
8739 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8740 */
8741 if ( pVmcsInfo->pvShadowVmcs
8742 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8743 {
8744 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8745 AssertRCReturn(rc, rc);
8746 }
8747
8748 /*
8749 * Flag that we need to re-import the host state if we switch to this VMCS before
8750 * executing guest or nested-guest code.
8751 */
8752 pVmcsInfo->idHostCpu = NIL_RTCPUID;
8753#endif
8754
8755 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8756 NOREF(idCpu);
8757 return VINF_SUCCESS;
8758}
8759
8760
8761/**
8762 * Leaves the VT-x session.
8763 *
8764 * @returns VBox status code.
8765 * @param pVCpu The cross context virtual CPU structure.
8766 *
8767 * @remarks No-long-jmp zone!!!
8768 */
8769static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8770{
8771 HM_DISABLE_PREEMPT(pVCpu);
8772 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8773 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8774 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8775
8776 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8777 and done this from the VMXR0ThreadCtxCallback(). */
8778 if (!pVCpu->hm.s.fLeaveDone)
8779 {
8780 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8781 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8782 pVCpu->hm.s.fLeaveDone = true;
8783 }
8784 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8785
8786 /*
8787 * !!! IMPORTANT !!!
8788 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8789 */
8790
8791 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8792 /** @todo Deregistering here means we need to VMCLEAR always
8793 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8794 * for calling VMMR0ThreadCtxHookDisable here! */
8795 VMMR0ThreadCtxHookDisable(pVCpu);
8796
8797 /* Leave HM context. This takes care of local init (term). */
8798 int rc = HMR0LeaveCpu(pVCpu);
8799
8800 HM_RESTORE_PREEMPT();
8801 return rc;
8802}
8803
8804
8805/**
8806 * Does the necessary state syncing before doing a longjmp to ring-3.
8807 *
8808 * @returns VBox status code.
8809 * @param pVCpu The cross context virtual CPU structure.
8810 *
8811 * @remarks No-long-jmp zone!!!
8812 */
8813DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8814{
8815 return hmR0VmxLeaveSession(pVCpu);
8816}
8817
8818
8819/**
8820 * Take necessary actions before going back to ring-3.
8821 *
8822 * An action requires us to go back to ring-3. This function does the necessary
8823 * steps before we can safely return to ring-3. This is not the same as longjmps
8824 * to ring-3, this is voluntary and prepares the guest so it may continue
8825 * executing outside HM (recompiler/IEM).
8826 *
8827 * @returns VBox status code.
8828 * @param pVCpu The cross context virtual CPU structure.
8829 * @param rcExit The reason for exiting to ring-3. Can be
8830 * VINF_VMM_UNKNOWN_RING3_CALL.
8831 */
8832static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8833{
8834 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8835
8836 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8837 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8838 {
8839 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8840 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8841 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8842 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8843 }
8844
8845 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8846 VMMRZCallRing3Disable(pVCpu);
8847 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8848
8849 /*
8850 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8851 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8852 *
8853 * This is because execution may continue from ring-3 and we would need to inject
8854 * the event from there (hence place it back in TRPM).
8855 */
8856 if (pVCpu->hm.s.Event.fPending)
8857 {
8858 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8859 Assert(!pVCpu->hm.s.Event.fPending);
8860
8861 /* Clear the events from the VMCS. */
8862 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8863 AssertRCReturn(rc, rc);
8864 }
8865#ifdef VBOX_STRICT
8866 else
8867 {
8868 /*
8869 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8870 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8871 * occasionally, see @bugref{9180#c42}.
8872 *
8873 * However, if the VM-entry failed, any VM entry-interruption info. field would
8874 * be left unmodified as the event would not have been injected to the guest. In
8875 * such cases, don't assert, we're not going to continue guest execution anyway.
8876 */
8877 uint32_t uExitReason;
8878 uint32_t uEntryIntInfo;
8879 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8880 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8881 AssertRC(rc);
8882 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8883 }
8884#endif
8885
8886 /*
8887 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8888 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8889 * (e.g. TPR below threshold).
8890 */
8891 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8892 {
8893 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8894 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8895 AssertRCReturn(rc, rc);
8896 }
8897
8898 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8899 and if we're injecting an event we should have a TRPM trap pending. */
8900 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8901#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8902 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8903#endif
8904
8905 /* Save guest state and restore host state bits. */
8906 int rc = hmR0VmxLeaveSession(pVCpu);
8907 AssertRCReturn(rc, rc);
8908 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8909
8910 /* Thread-context hooks are unregistered at this point!!! */
8911
8912 /* Sync recompiler state. */
8913 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8914 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8915 | CPUM_CHANGED_LDTR
8916 | CPUM_CHANGED_GDTR
8917 | CPUM_CHANGED_IDTR
8918 | CPUM_CHANGED_TR
8919 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8920 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8921 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8922 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8923
8924 Assert(!pVCpu->hm.s.fClearTrapFlag);
8925
8926 /* Update the exit-to-ring 3 reason. */
8927 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8928
8929 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8930 if ( rcExit != VINF_EM_RAW_INTERRUPT
8931 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8932 {
8933 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8934 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8935 }
8936
8937 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8938
8939 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8940 VMMRZCallRing3RemoveNotification(pVCpu);
8941 VMMRZCallRing3Enable(pVCpu);
8942
8943 return rc;
8944}
8945
8946
8947/**
8948 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8949 * longjump to ring-3 and possibly get preempted.
8950 *
8951 * @returns VBox status code.
8952 * @param pVCpu The cross context virtual CPU structure.
8953 * @param enmOperation The operation causing the ring-3 longjump.
8954 * @param pvUser User argument, currently unused, NULL.
8955 */
8956static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
8957{
8958 RT_NOREF(pvUser);
8959 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8960 {
8961 /*
8962 * !!! IMPORTANT !!!
8963 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8964 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8965 */
8966 VMMRZCallRing3RemoveNotification(pVCpu);
8967 VMMRZCallRing3Disable(pVCpu);
8968 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
8969 RTThreadPreemptDisable(&PreemptState);
8970
8971 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8972 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8973 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8974 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8975
8976#if HC_ARCH_BITS == 64
8977 /* Restore host-state bits that VT-x only restores partially. */
8978 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8979 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8980 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8981 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8982#endif
8983
8984 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8985 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8986 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8987
8988 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8989 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8990 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8991
8992 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8993 cleared as part of importing the guest state above. */
8994 hmR0VmxClearVmcs(pVmcsInfo);
8995
8996 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8997 VMMR0ThreadCtxHookDisable(pVCpu);
8998 HMR0LeaveCpu(pVCpu);
8999 RTThreadPreemptRestore(&PreemptState);
9000 return VINF_SUCCESS;
9001 }
9002
9003 Assert(pVCpu);
9004 Assert(pvUser);
9005 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9006 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9007
9008 VMMRZCallRing3Disable(pVCpu);
9009 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9010
9011 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
9012
9013 int rc = hmR0VmxLongJmpToRing3(pVCpu);
9014 AssertRCReturn(rc, rc);
9015
9016 VMMRZCallRing3Enable(pVCpu);
9017 return VINF_SUCCESS;
9018}
9019
9020
9021/**
9022 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
9023 * stack.
9024 *
9025 * @returns Strict VBox status code (i.e. informational status codes too).
9026 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
9027 * @param pVCpu The cross context virtual CPU structure.
9028 * @param uValue The value to push to the guest stack.
9029 */
9030static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
9031{
9032 /*
9033 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
9034 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
9035 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
9036 */
9037 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9038 if (pCtx->sp == 1)
9039 return VINF_EM_RESET;
9040 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
9041 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
9042 AssertRC(rc);
9043 return rc;
9044}
9045
9046
9047/**
9048 * Injects an event into the guest upon VM-entry by updating the relevant fields
9049 * in the VM-entry area in the VMCS.
9050 *
9051 * @returns Strict VBox status code (i.e. informational status codes too).
9052 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
9053 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
9054 *
9055 * @param pVCpu The cross context virtual CPU structure.
9056 * @param pVmxTransient The VMX-transient structure.
9057 * @param pEvent The event being injected.
9058 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
9059 * will be updated if necessary. This cannot not be NULL.
9060 * @param fStepping Whether we're single-stepping guest execution and should
9061 * return VINF_EM_DBG_STEPPED if the event is injected
9062 * directly (registers modified by us, not by hardware on
9063 * VM-entry).
9064 */
9065static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
9066 uint32_t *pfIntrState)
9067{
9068 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
9069 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
9070 Assert(pfIntrState);
9071
9072 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9073 uint32_t u32IntInfo = pEvent->u64IntInfo;
9074 uint32_t const u32ErrCode = pEvent->u32ErrCode;
9075 uint32_t const cbInstr = pEvent->cbInstr;
9076 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
9077 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
9078 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
9079
9080#ifdef VBOX_STRICT
9081 /*
9082 * Validate the error-code-valid bit for hardware exceptions.
9083 * No error codes for exceptions in real-mode.
9084 *
9085 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9086 */
9087 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
9088 && !CPUMIsGuestInRealModeEx(pCtx))
9089 {
9090 switch (uVector)
9091 {
9092 case X86_XCPT_PF:
9093 case X86_XCPT_DF:
9094 case X86_XCPT_TS:
9095 case X86_XCPT_NP:
9096 case X86_XCPT_SS:
9097 case X86_XCPT_GP:
9098 case X86_XCPT_AC:
9099 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
9100 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
9101 RT_FALL_THRU();
9102 default:
9103 break;
9104 }
9105 }
9106
9107 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
9108 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
9109 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9110#endif
9111
9112 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
9113
9114 /*
9115 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
9116 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
9117 * interrupt handler in the (real-mode) guest.
9118 *
9119 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
9120 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
9121 */
9122 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
9123 {
9124 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
9125 {
9126 /*
9127 * For CPUs with unrestricted guest execution enabled and with the guest
9128 * in real-mode, we must not set the deliver-error-code bit.
9129 *
9130 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
9131 */
9132 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
9133 }
9134 else
9135 {
9136 PVM pVM = pVCpu->CTX_SUFF(pVM);
9137 Assert(PDMVmmDevHeapIsEnabled(pVM));
9138 Assert(pVM->hm.s.vmx.pRealModeTSS);
9139 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
9140
9141 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
9142 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9143 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
9144 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
9145 AssertRCReturn(rc2, rc2);
9146
9147 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
9148 size_t const cbIdtEntry = sizeof(X86IDTR16);
9149 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
9150 {
9151 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
9152 if (uVector == X86_XCPT_DF)
9153 return VINF_EM_RESET;
9154
9155 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
9156 No error codes for exceptions in real-mode. */
9157 if (uVector == X86_XCPT_GP)
9158 {
9159 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
9160 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9161 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9162 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9163 HMEVENT EventXcptDf;
9164 RT_ZERO(EventXcptDf);
9165 EventXcptDf.u64IntInfo = uXcptDfInfo;
9166 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
9167 }
9168
9169 /*
9170 * If we're injecting an event with no valid IDT entry, inject a #GP.
9171 * No error codes for exceptions in real-mode.
9172 *
9173 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9174 */
9175 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
9176 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9177 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9178 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9179 HMEVENT EventXcptGp;
9180 RT_ZERO(EventXcptGp);
9181 EventXcptGp.u64IntInfo = uXcptGpInfo;
9182 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
9183 }
9184
9185 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
9186 uint16_t uGuestIp = pCtx->ip;
9187 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
9188 {
9189 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
9190 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
9191 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9192 }
9193 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
9194 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9195
9196 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
9197 X86IDTR16 IdtEntry;
9198 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
9199 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
9200 AssertRCReturn(rc2, rc2);
9201
9202 /* Construct the stack frame for the interrupt/exception handler. */
9203 VBOXSTRICTRC rcStrict;
9204 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
9205 if (rcStrict == VINF_SUCCESS)
9206 {
9207 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
9208 if (rcStrict == VINF_SUCCESS)
9209 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
9210 }
9211
9212 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
9213 if (rcStrict == VINF_SUCCESS)
9214 {
9215 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
9216 pCtx->rip = IdtEntry.offSel;
9217 pCtx->cs.Sel = IdtEntry.uSel;
9218 pCtx->cs.ValidSel = IdtEntry.uSel;
9219 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
9220 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
9221 && uVector == X86_XCPT_PF)
9222 pCtx->cr2 = GCPtrFault;
9223
9224 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
9225 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
9226 | HM_CHANGED_GUEST_RSP);
9227
9228 /*
9229 * If we delivered a hardware exception (other than an NMI) and if there was
9230 * block-by-STI in effect, we should clear it.
9231 */
9232 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9233 {
9234 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
9235 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
9236 Log4Func(("Clearing inhibition due to STI\n"));
9237 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
9238 }
9239
9240 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
9241 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
9242
9243 /*
9244 * The event has been truly dispatched to the guest. Mark it as no longer pending so
9245 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
9246 */
9247 pVCpu->hm.s.Event.fPending = false;
9248
9249 /*
9250 * If we eventually support nested-guest execution without unrestricted guest execution,
9251 * we should set fInterceptEvents here.
9252 */
9253 Assert(!pVmxTransient->fIsNestedGuest);
9254
9255 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
9256 if (fStepping)
9257 rcStrict = VINF_EM_DBG_STEPPED;
9258 }
9259 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9260 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9261 return rcStrict;
9262 }
9263 }
9264
9265 /*
9266 * Validate.
9267 */
9268 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9269 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9270
9271 /*
9272 * Inject the event into the VMCS.
9273 */
9274 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9275 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9276 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9277 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9278 AssertRCReturn(rc, rc);
9279
9280 /*
9281 * Update guest CR2 if this is a page-fault.
9282 */
9283 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9284 pCtx->cr2 = GCPtrFault;
9285
9286 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9287 return VINF_SUCCESS;
9288}
9289
9290
9291/**
9292 * Evaluates the event to be delivered to the guest and sets it as the pending
9293 * event.
9294 *
9295 * @returns Strict VBox status code (i.e. informational status codes too).
9296 * @param pVCpu The cross context virtual CPU structure.
9297 * @param pVmxTransient The VMX-transient structure.
9298 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9299 */
9300static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9301{
9302 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9303 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9304 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9305
9306 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
9307 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
9308 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9309 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9310 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9311
9312 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9313 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9314 Assert(!fBlockSti || pCtx->eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9315 Assert(!TRPMHasTrap(pVCpu));
9316 Assert(pfIntrState);
9317
9318 *pfIntrState = fIntrState;
9319
9320 /*
9321 * Toggling of interrupt force-flags here is safe since we update TRPM on premature exits
9322 * to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must NOT restore these force-flags.
9323 */
9324 /** @todo SMI. SMIs take priority over NMIs. */
9325 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts. */
9326 {
9327 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
9328 if ( !pVCpu->hm.s.Event.fPending
9329 && !fBlockNmi
9330 && !fBlockSti
9331 && !fBlockMovSS)
9332 {
9333#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9334 if ( fIsNestedGuest
9335 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
9336 return IEMExecVmxVmexitXcptNmi(pVCpu);
9337#endif
9338 hmR0VmxSetPendingXcptNmi(pVCpu);
9339 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9340 Log4Func(("Pending NMI\n"));
9341 }
9342 else if (!fIsNestedGuest)
9343 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9344 }
9345 /*
9346 * Check if the guest can receive external interrupts (PIC/APIC). Once PDMGetInterrupt() returns
9347 * a valid interrupt we -must- deliver the interrupt. We can no longer re-request it from the APIC.
9348 */
9349 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9350 && !pVCpu->hm.s.fSingleInstruction)
9351 {
9352 Assert(!DBGFIsStepping(pVCpu));
9353 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9354 AssertRCReturn(rc, rc);
9355 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
9356 if ( !pVCpu->hm.s.Event.fPending
9357 && !fBlockInt
9358 && !fBlockSti
9359 && !fBlockMovSS)
9360 {
9361#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9362 if ( fIsNestedGuest
9363 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9364 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9365 {
9366 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
9367 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9368 return rcStrict;
9369 }
9370#endif
9371 uint8_t u8Interrupt;
9372 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9373 if (RT_SUCCESS(rc))
9374 {
9375#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9376 if ( fIsNestedGuest
9377 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9378 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9379 {
9380 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9381 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9382 return rcStrict;
9383 }
9384#endif
9385 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9386 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9387 }
9388 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9389 {
9390 if ( !fIsNestedGuest
9391 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9392 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9393 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9394
9395 /*
9396 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9397 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9398 * need to re-set this force-flag here.
9399 */
9400 }
9401 else
9402 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9403 }
9404 else if (!fIsNestedGuest)
9405 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9406 }
9407
9408 return VINF_SUCCESS;
9409}
9410
9411
9412/**
9413 * Injects any pending events into the guest if the guest is in a state to
9414 * receive them.
9415 *
9416 * @returns Strict VBox status code (i.e. informational status codes too).
9417 * @param pVCpu The cross context virtual CPU structure.
9418 * @param pVmxTransient The VMX-transient structure.
9419 * @param fIntrState The VT-x guest-interruptibility state.
9420 * @param fStepping Whether we are single-stepping the guest using the
9421 * hypervisor debugger and should return
9422 * VINF_EM_DBG_STEPPED if the event was dispatched
9423 * directly.
9424 */
9425static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9426{
9427 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9428 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9429
9430 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9431 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9432
9433 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9434 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9435 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9436 Assert(!TRPMHasTrap(pVCpu));
9437
9438 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9439 if (pVCpu->hm.s.Event.fPending)
9440 {
9441 /*
9442 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9443 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9444 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9445 *
9446 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9447 */
9448 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9449#ifdef VBOX_STRICT
9450 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9451 {
9452 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9453 Assert(!fBlockInt);
9454 Assert(!fBlockSti);
9455 Assert(!fBlockMovSS);
9456 }
9457 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9458 {
9459 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9460 Assert(!fBlockSti);
9461 Assert(!fBlockMovSS);
9462 Assert(!fBlockNmi);
9463 }
9464#endif
9465 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9466 uIntType));
9467
9468 /*
9469 * Inject the event and get any changes to the guest-interruptibility state.
9470 *
9471 * The guest-interruptibility state may need to be updated if we inject the event
9472 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9473 */
9474 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9475 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9476
9477 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9478 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9479 else
9480 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9481 }
9482
9483 /*
9484 * Update the guest-interruptibility state.
9485 *
9486 * This is required for the real-on-v86 software interrupt injection case above, as well as
9487 * updates to the guest state from ring-3 or IEM/REM.
9488 */
9489 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9490 AssertRCReturn(rc, rc);
9491
9492 /*
9493 * There's no need to clear the VM-entry interruption-information field here if we're not
9494 * injecting anything. VT-x clears the valid bit on every VM-exit.
9495 *
9496 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9497 */
9498
9499 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9500 NOREF(fBlockMovSS); NOREF(fBlockSti);
9501 return rcStrict;
9502}
9503
9504
9505/**
9506 * Enters the VT-x session.
9507 *
9508 * @returns VBox status code.
9509 * @param pVCpu The cross context virtual CPU structure.
9510 */
9511VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9512{
9513 AssertPtr(pVCpu);
9514 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9515 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9516
9517 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9518 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9519 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9520
9521#ifdef VBOX_STRICT
9522 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9523 RTCCUINTREG uHostCr4 = ASMGetCR4();
9524 if (!(uHostCr4 & X86_CR4_VMXE))
9525 {
9526 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9527 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9528 }
9529#endif
9530
9531 /*
9532 * Load the appropriate VMCS as the current and active one.
9533 */
9534 PVMXVMCSINFO pVmcsInfo;
9535 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9536 if (!fInNestedGuestMode)
9537 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9538 else
9539 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9540 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9541 if (RT_SUCCESS(rc))
9542 {
9543 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9544 pVCpu->hm.s.fLeaveDone = false;
9545 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9546
9547 /*
9548 * Do the EMT scheduled L1D flush here if needed.
9549 */
9550 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9551 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9552 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9553 hmR0MdsClear();
9554 }
9555 return rc;
9556}
9557
9558
9559/**
9560 * The thread-context callback (only on platforms which support it).
9561 *
9562 * @param enmEvent The thread-context event.
9563 * @param pVCpu The cross context virtual CPU structure.
9564 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9565 * @thread EMT(pVCpu)
9566 */
9567VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9568{
9569 AssertPtr(pVCpu);
9570 RT_NOREF1(fGlobalInit);
9571
9572 switch (enmEvent)
9573 {
9574 case RTTHREADCTXEVENT_OUT:
9575 {
9576 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9577 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9578 VMCPU_ASSERT_EMT(pVCpu);
9579
9580 /* No longjmps (logger flushes, locks) in this fragile context. */
9581 VMMRZCallRing3Disable(pVCpu);
9582 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9583
9584 /* Restore host-state (FPU, debug etc.) */
9585 if (!pVCpu->hm.s.fLeaveDone)
9586 {
9587 /*
9588 * Do -not- import the guest-state here as we might already be in the middle of importing
9589 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9590 */
9591 hmR0VmxLeave(pVCpu, false /* fImportState */);
9592 pVCpu->hm.s.fLeaveDone = true;
9593 }
9594
9595 /* Leave HM context, takes care of local init (term). */
9596 int rc = HMR0LeaveCpu(pVCpu);
9597 AssertRC(rc);
9598
9599 /* Restore longjmp state. */
9600 VMMRZCallRing3Enable(pVCpu);
9601 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9602 break;
9603 }
9604
9605 case RTTHREADCTXEVENT_IN:
9606 {
9607 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9608 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9609 VMCPU_ASSERT_EMT(pVCpu);
9610
9611 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9612 VMMRZCallRing3Disable(pVCpu);
9613 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9614
9615 /* Initialize the bare minimum state required for HM. This takes care of
9616 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9617 int rc = hmR0EnterCpu(pVCpu);
9618 AssertRC(rc);
9619 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9620 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9621
9622 /* Load the active VMCS as the current one. */
9623 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9624 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9625 AssertRC(rc);
9626 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9627 pVCpu->hm.s.fLeaveDone = false;
9628
9629 /* Do the EMT scheduled L1D flush if needed. */
9630 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9631 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9632
9633 /* Restore longjmp state. */
9634 VMMRZCallRing3Enable(pVCpu);
9635 break;
9636 }
9637
9638 default:
9639 break;
9640 }
9641}
9642
9643
9644/**
9645 * Exports the host state into the VMCS host-state area.
9646 * Sets up the VM-exit MSR-load area.
9647 *
9648 * The CPU state will be loaded from these fields on every successful VM-exit.
9649 *
9650 * @returns VBox status code.
9651 * @param pVCpu The cross context virtual CPU structure.
9652 *
9653 * @remarks No-long-jump zone!!!
9654 */
9655static int hmR0VmxExportHostState(PVMCPU pVCpu)
9656{
9657 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9658
9659 int rc = VINF_SUCCESS;
9660 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9661 {
9662 rc = hmR0VmxExportHostControlRegs();
9663 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9664
9665 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9666 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9667
9668 rc = hmR0VmxExportHostMsrs(pVCpu);
9669 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9670
9671 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9672 }
9673 return rc;
9674}
9675
9676
9677/**
9678 * Saves the host state in the VMCS host-state.
9679 *
9680 * @returns VBox status code.
9681 * @param pVCpu The cross context virtual CPU structure.
9682 *
9683 * @remarks No-long-jump zone!!!
9684 */
9685VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9686{
9687 AssertPtr(pVCpu);
9688 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9689
9690 /*
9691 * Export the host state here while entering HM context.
9692 * When thread-context hooks are used, we might get preempted and have to re-save the host
9693 * state but most of the time we won't be, so do it here before we disable interrupts.
9694 */
9695 return hmR0VmxExportHostState(pVCpu);
9696}
9697
9698
9699/**
9700 * Exports the guest state into the VMCS guest-state area.
9701 *
9702 * The will typically be done before VM-entry when the guest-CPU state and the
9703 * VMCS state may potentially be out of sync.
9704 *
9705 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9706 * VM-entry controls.
9707 * Sets up the appropriate VMX non-root function to execute guest code based on
9708 * the guest CPU mode.
9709 *
9710 * @returns VBox strict status code.
9711 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9712 * without unrestricted guest execution and the VMMDev is not presently
9713 * mapped (e.g. EFI32).
9714 *
9715 * @param pVCpu The cross context virtual CPU structure.
9716 * @param pVmxTransient The VMX-transient structure.
9717 *
9718 * @remarks No-long-jump zone!!!
9719 */
9720static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9721{
9722 AssertPtr(pVCpu);
9723 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9724 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9725
9726 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9727
9728 /*
9729 * Determine real-on-v86 mode.
9730 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9731 */
9732 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9733 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9734 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9735 pVmcsInfo->RealMode. fRealOnV86Active = false;
9736 else
9737 {
9738 Assert(!pVmxTransient->fIsNestedGuest);
9739 pVmcsInfo->RealMode.fRealOnV86Active = true;
9740 }
9741
9742 /*
9743 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9744 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9745 */
9746 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9747 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9748 * be a need to evaluate this everytime since I'm pretty sure we intercept
9749 * all guest paging mode changes. */
9750 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9751 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9752
9753 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9754 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9755
9756 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9757 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9758
9759 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9760 if (rcStrict == VINF_SUCCESS)
9761 { /* likely */ }
9762 else
9763 {
9764 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9765 return rcStrict;
9766 }
9767
9768 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9769 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9770
9771 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9772 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9773
9774 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9775 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9776
9777 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9778 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9779
9780 rc = hmR0VmxExportGuestRip(pVCpu);
9781 rc |= hmR0VmxExportGuestRsp(pVCpu);
9782 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9783 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9784
9785 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9786 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9787
9788 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9789 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9790 | HM_CHANGED_GUEST_CR2
9791 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9792 | HM_CHANGED_GUEST_X87
9793 | HM_CHANGED_GUEST_SSE_AVX
9794 | HM_CHANGED_GUEST_OTHER_XSAVE
9795 | HM_CHANGED_GUEST_XCRx
9796 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9797 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9798 | HM_CHANGED_GUEST_TSC_AUX
9799 | HM_CHANGED_GUEST_OTHER_MSRS
9800 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9801
9802 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9803 return rc;
9804}
9805
9806
9807/**
9808 * Exports the state shared between the host and guest into the VMCS.
9809 *
9810 * @param pVCpu The cross context virtual CPU structure.
9811 * @param pVmxTransient The VMX-transient structure.
9812 *
9813 * @remarks No-long-jump zone!!!
9814 */
9815static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9816{
9817 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9818 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9819
9820 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9821 {
9822 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9823 AssertRC(rc);
9824 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9825
9826 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9827 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9828 {
9829 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9830 AssertRC(rc);
9831 }
9832 }
9833
9834 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9835 {
9836 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9837 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9838 }
9839
9840 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9841 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9842}
9843
9844
9845/**
9846 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9847 *
9848 * @returns Strict VBox status code (i.e. informational status codes too).
9849 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9850 * without unrestricted guest execution and the VMMDev is not presently
9851 * mapped (e.g. EFI32).
9852 *
9853 * @param pVCpu The cross context virtual CPU structure.
9854 * @param pVmxTransient The VMX-transient structure.
9855 *
9856 * @remarks No-long-jump zone!!!
9857 */
9858static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9859{
9860 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9861 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9862 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9863
9864#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9865 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9866#endif
9867
9868 /*
9869 * For many exits it's only RIP that changes and hence try to export it first
9870 * without going through a lot of change flag checks.
9871 */
9872 VBOXSTRICTRC rcStrict;
9873 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9874 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9875 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9876 {
9877 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9878 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9879 { /* likely */}
9880 else
9881 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9882 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9883 }
9884 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9885 {
9886 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9887 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9888 { /* likely */}
9889 else
9890 {
9891 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9892 VBOXSTRICTRC_VAL(rcStrict)));
9893 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9894 return rcStrict;
9895 }
9896 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9897 }
9898 else
9899 rcStrict = VINF_SUCCESS;
9900
9901#ifdef VBOX_STRICT
9902 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9903 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9904 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9905 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9906 ("fCtxChanged=%#RX64\n", fCtxChanged));
9907#endif
9908 return rcStrict;
9909}
9910
9911
9912/**
9913 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9914 * and update error record fields accordingly.
9915 *
9916 * @returns VMX_IGS_* error codes.
9917 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9918 * wrong with the guest state.
9919 *
9920 * @param pVCpu The cross context virtual CPU structure.
9921 * @param pVmcsInfo The VMCS info. object.
9922 *
9923 * @remarks This function assumes our cache of the VMCS controls
9924 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9925 */
9926static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9927{
9928#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9929#define HMVMX_CHECK_BREAK(expr, err) do { \
9930 if (!(expr)) { uError = (err); break; } \
9931 } while (0)
9932
9933 int rc;
9934 PVM pVM = pVCpu->CTX_SUFF(pVM);
9935 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9936 uint32_t uError = VMX_IGS_ERROR;
9937 uint32_t u32Val;
9938 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9939
9940 do
9941 {
9942 /*
9943 * CR0.
9944 */
9945 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9946 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9947 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9948 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9949 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9950 if (fUnrestrictedGuest)
9951 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
9952
9953 uint32_t u32GuestCr0;
9954 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
9955 AssertRCBreak(rc);
9956 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9957 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9958 if ( !fUnrestrictedGuest
9959 && (u32GuestCr0 & X86_CR0_PG)
9960 && !(u32GuestCr0 & X86_CR0_PE))
9961 {
9962 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9963 }
9964
9965 /*
9966 * CR4.
9967 */
9968 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9969 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9970 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9971
9972 uint32_t u32GuestCr4;
9973 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
9974 AssertRCBreak(rc);
9975 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9976 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9977
9978 /*
9979 * IA32_DEBUGCTL MSR.
9980 */
9981 uint64_t u64Val;
9982 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9983 AssertRCBreak(rc);
9984 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9985 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9986 {
9987 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9988 }
9989 uint64_t u64DebugCtlMsr = u64Val;
9990
9991#ifdef VBOX_STRICT
9992 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9993 AssertRCBreak(rc);
9994 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9995#endif
9996 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9997
9998 /*
9999 * RIP and RFLAGS.
10000 */
10001 uint32_t u32Eflags;
10002#if HC_ARCH_BITS == 64
10003 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10004 AssertRCBreak(rc);
10005 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10006 if ( !fLongModeGuest
10007 || !pCtx->cs.Attr.n.u1Long)
10008 {
10009 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10010 }
10011 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10012 * must be identical if the "IA-32e mode guest" VM-entry
10013 * control is 1 and CS.L is 1. No check applies if the
10014 * CPU supports 64 linear-address bits. */
10015
10016 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10017 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10018 AssertRCBreak(rc);
10019 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10020 VMX_IGS_RFLAGS_RESERVED);
10021 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10022 u32Eflags = u64Val;
10023#else
10024 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10025 AssertRCBreak(rc);
10026 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10027 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10028#endif
10029
10030 if ( fLongModeGuest
10031 || ( fUnrestrictedGuest
10032 && !(u32GuestCr0 & X86_CR0_PE)))
10033 {
10034 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10035 }
10036
10037 uint32_t u32EntryInfo;
10038 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10039 AssertRCBreak(rc);
10040 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10041 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10042
10043 /*
10044 * 64-bit checks.
10045 */
10046#if HC_ARCH_BITS == 64
10047 if (fLongModeGuest)
10048 {
10049 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10050 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10051 }
10052
10053 if ( !fLongModeGuest
10054 && (u32GuestCr4 & X86_CR4_PCIDE))
10055 {
10056 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10057 }
10058
10059 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10060 * 51:32 beyond the processor's physical-address width are 0. */
10061
10062 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10063 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10064 {
10065 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10066 }
10067
10068 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10069 AssertRCBreak(rc);
10070 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10071
10072 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10073 AssertRCBreak(rc);
10074 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10075#endif
10076
10077 /*
10078 * PERF_GLOBAL MSR.
10079 */
10080 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10081 {
10082 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10083 AssertRCBreak(rc);
10084 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10085 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10086 }
10087
10088 /*
10089 * PAT MSR.
10090 */
10091 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10092 {
10093 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10094 AssertRCBreak(rc);
10095 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10096 for (unsigned i = 0; i < 8; i++)
10097 {
10098 uint8_t u8Val = (u64Val & 0xff);
10099 if ( u8Val != 0 /* UC */
10100 && u8Val != 1 /* WC */
10101 && u8Val != 4 /* WT */
10102 && u8Val != 5 /* WP */
10103 && u8Val != 6 /* WB */
10104 && u8Val != 7 /* UC- */)
10105 {
10106 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10107 }
10108 u64Val >>= 8;
10109 }
10110 }
10111
10112 /*
10113 * EFER MSR.
10114 */
10115 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10116 {
10117 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10118 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10119 AssertRCBreak(rc);
10120 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10121 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10122 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10123 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10124 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10125 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10126 * iemVmxVmentryCheckGuestState(). */
10127 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10128 || !(u32GuestCr0 & X86_CR0_PG)
10129 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10130 VMX_IGS_EFER_LMA_LME_MISMATCH);
10131 }
10132
10133 /*
10134 * Segment registers.
10135 */
10136 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10137 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10138 if (!(u32Eflags & X86_EFL_VM))
10139 {
10140 /* CS */
10141 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10142 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10143 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10144 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10145 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10146 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10147 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10148 /* CS cannot be loaded with NULL in protected mode. */
10149 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10150 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10151 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10152 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10153 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10154 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10155 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10156 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10157 else
10158 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10159
10160 /* SS */
10161 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10162 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10163 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10164 if ( !(pCtx->cr0 & X86_CR0_PE)
10165 || pCtx->cs.Attr.n.u4Type == 3)
10166 {
10167 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10168 }
10169 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10170 {
10171 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10172 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10173 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10174 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10175 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10176 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10177 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10178 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10179 }
10180
10181 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10182 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10183 {
10184 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10185 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10186 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10187 || pCtx->ds.Attr.n.u4Type > 11
10188 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10189 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10190 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10191 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10192 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10193 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10194 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10195 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10196 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10197 }
10198 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10199 {
10200 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10201 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10202 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10203 || pCtx->es.Attr.n.u4Type > 11
10204 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10205 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10206 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10207 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10208 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10209 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10210 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10211 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10212 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10213 }
10214 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10215 {
10216 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10217 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10218 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10219 || pCtx->fs.Attr.n.u4Type > 11
10220 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10221 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10222 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10223 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10224 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10225 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10226 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10227 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10228 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10229 }
10230 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10231 {
10232 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10233 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10234 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10235 || pCtx->gs.Attr.n.u4Type > 11
10236 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10237 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10238 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10239 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10240 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10241 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10242 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10243 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10244 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10245 }
10246 /* 64-bit capable CPUs. */
10247#if HC_ARCH_BITS == 64
10248 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10249 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10250 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10251 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10252 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10253 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10254 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10255 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10256 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10257 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10258 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10259#endif
10260 }
10261 else
10262 {
10263 /* V86 mode checks. */
10264 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10265 if (pVmcsInfo->RealMode.fRealOnV86Active)
10266 {
10267 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10268 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10269 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10270 }
10271 else
10272 {
10273 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10274 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10275 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10276 }
10277
10278 /* CS */
10279 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10280 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10281 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10282 /* SS */
10283 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10284 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10285 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10286 /* DS */
10287 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10288 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10289 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10290 /* ES */
10291 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10292 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10293 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10294 /* FS */
10295 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10296 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10297 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10298 /* GS */
10299 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10300 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10301 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10302 /* 64-bit capable CPUs. */
10303#if HC_ARCH_BITS == 64
10304 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10305 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10306 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10307 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10308 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10309 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10310 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10311 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10312 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10313 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10314 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10315#endif
10316 }
10317
10318 /*
10319 * TR.
10320 */
10321 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10322 /* 64-bit capable CPUs. */
10323#if HC_ARCH_BITS == 64
10324 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10325#endif
10326 if (fLongModeGuest)
10327 {
10328 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10329 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10330 }
10331 else
10332 {
10333 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10334 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10335 VMX_IGS_TR_ATTR_TYPE_INVALID);
10336 }
10337 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10338 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10339 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10340 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10341 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10342 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10343 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10344 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10345
10346 /*
10347 * GDTR and IDTR.
10348 */
10349#if HC_ARCH_BITS == 64
10350 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10351 AssertRCBreak(rc);
10352 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10353
10354 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10355 AssertRCBreak(rc);
10356 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10357#endif
10358
10359 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10360 AssertRCBreak(rc);
10361 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10362
10363 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10364 AssertRCBreak(rc);
10365 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10366
10367 /*
10368 * Guest Non-Register State.
10369 */
10370 /* Activity State. */
10371 uint32_t u32ActivityState;
10372 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10373 AssertRCBreak(rc);
10374 HMVMX_CHECK_BREAK( !u32ActivityState
10375 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10376 VMX_IGS_ACTIVITY_STATE_INVALID);
10377 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10378 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10379 uint32_t u32IntrState;
10380 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10381 AssertRCBreak(rc);
10382 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10383 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10384 {
10385 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10386 }
10387
10388 /** @todo Activity state and injecting interrupts. Left as a todo since we
10389 * currently don't use activity states but ACTIVE. */
10390
10391 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10392 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10393
10394 /* Guest interruptibility-state. */
10395 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10396 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10397 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10398 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10399 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10400 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10401 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10402 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10403 {
10404 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10405 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10406 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10407 }
10408 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10409 {
10410 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10411 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10412 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10413 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10414 }
10415 /** @todo Assumes the processor is not in SMM. */
10416 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10417 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10418 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10419 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10420 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10421 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10422 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10423 {
10424 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10425 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10426 }
10427
10428 /* Pending debug exceptions. */
10429#if HC_ARCH_BITS == 64
10430 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10431 AssertRCBreak(rc);
10432 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10433 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10434 u32Val = u64Val; /* For pending debug exceptions checks below. */
10435#else
10436 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10437 AssertRCBreak(rc);
10438 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10439 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10440#endif
10441
10442 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10443 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10444 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10445 {
10446 if ( (u32Eflags & X86_EFL_TF)
10447 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10448 {
10449 /* Bit 14 is PendingDebug.BS. */
10450 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10451 }
10452 if ( !(u32Eflags & X86_EFL_TF)
10453 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10454 {
10455 /* Bit 14 is PendingDebug.BS. */
10456 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10457 }
10458 }
10459
10460 /* VMCS link pointer. */
10461 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10462 AssertRCBreak(rc);
10463 if (u64Val != UINT64_C(0xffffffffffffffff))
10464 {
10465 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10466 /** @todo Bits beyond the processor's physical-address width MBZ. */
10467 /** @todo SMM checks. */
10468 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10469 Assert(pVmcsInfo->pvShadowVmcs);
10470 VMXVMCSREVID VmcsRevId;
10471 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10472 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10473 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10474 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10475 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10476 }
10477
10478 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10479 * not using nested paging? */
10480 if ( pVM->hm.s.fNestedPaging
10481 && !fLongModeGuest
10482 && CPUMIsGuestInPAEModeEx(pCtx))
10483 {
10484 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10485 AssertRCBreak(rc);
10486 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10487
10488 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10489 AssertRCBreak(rc);
10490 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10491
10492 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10493 AssertRCBreak(rc);
10494 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10495
10496 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10497 AssertRCBreak(rc);
10498 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10499 }
10500
10501 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10502 if (uError == VMX_IGS_ERROR)
10503 uError = VMX_IGS_REASON_NOT_FOUND;
10504 } while (0);
10505
10506 pVCpu->hm.s.u32HMError = uError;
10507 return uError;
10508
10509#undef HMVMX_ERROR_BREAK
10510#undef HMVMX_CHECK_BREAK
10511}
10512
10513
10514/**
10515 * Map the APIC-access page for virtualizing APIC accesses.
10516 *
10517 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10518 * this not done as part of exporting guest state, see @bugref{8721}.
10519 *
10520 * @returns VBox status code.
10521 * @param pVCpu The cross context virtual CPU structure.
10522 */
10523static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10524{
10525 PVM pVM = pVCpu->CTX_SUFF(pVM);
10526 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10527
10528 Assert(PDMHasApic(pVM));
10529 Assert(u64MsrApicBase);
10530
10531 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10532 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10533
10534 /* Unalias the existing mapping. */
10535 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10536 AssertRCReturn(rc, rc);
10537
10538 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10539 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10540 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10541 AssertRCReturn(rc, rc);
10542
10543 /* Update the per-VCPU cache of the APIC base MSR. */
10544 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10545 return VINF_SUCCESS;
10546}
10547
10548
10549/**
10550 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10551 * CPU.
10552 *
10553 * @param idCpu The ID for the CPU the function is called on.
10554 * @param pvUser1 Null, not used.
10555 * @param pvUser2 Null, not used.
10556 */
10557static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10558{
10559 RT_NOREF3(idCpu, pvUser1, pvUser2);
10560 VMXDispatchHostNmi();
10561}
10562
10563
10564/**
10565 * Dispatching an NMI on the host CPU that received it.
10566 *
10567 * @returns VBox status code.
10568 * @param pVCpu The cross context virtual CPU structure.
10569 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10570 * executing when receiving the host NMI in VMX non-root
10571 * operation.
10572 */
10573static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10574{
10575 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
10576
10577 /*
10578 * We don't want to delay dispatching the NMI any more than we have to. However,
10579 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10580 * after executing guest or nested-guest code for the following reasons:
10581 *
10582 * - We would need to perform VMREADs with interrupts disabled and is orders of
10583 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
10584 * supported by the host hypervisor.
10585 *
10586 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10587 * longer period of time just for handling an edge case like host NMIs which do
10588 * not occur nearly as frequently as other VM-exits.
10589 *
10590 * Let's cover the most likely scenario first. Check if we are on the target CPU
10591 * and dispatch the NMI right away. This should be much faster than calling into
10592 * RTMpOnSpecific() machinery.
10593 */
10594 bool fDispatched = false;
10595 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10596 if (idCpu == RTMpCpuId())
10597 {
10598 VMXDispatchHostNmi();
10599 fDispatched = true;
10600 }
10601 ASMSetFlags(fEFlags);
10602 if (fDispatched)
10603 {
10604 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10605 return VINF_SUCCESS;
10606 }
10607
10608 /*
10609 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10610 * there should be no race or recursion even if we are unlucky enough to be preempted
10611 * (to the target CPU) without dispatching the host NMI above.
10612 */
10613 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10614 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10615}
10616
10617
10618#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10619/**
10620 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10621 * nested-guest using hardware-assisted VMX.
10622 *
10623 * @param pVCpu The cross context virtual CPU structure.
10624 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10625 * @param pVmcsInfoGst The guest VMCS info. object.
10626 */
10627static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10628{
10629 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10630 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10631 Assert(pu64MsrBitmap);
10632
10633 /*
10634 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10635 * MSR that is intercepted by the guest is also intercepted while executing the
10636 * nested-guest using hardware-assisted VMX.
10637 *
10638 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10639 * nested-guest VM-exit even if the outer guest is not intercepting some
10640 * MSRs. We cannot assume the caller has initialized the nested-guest
10641 * MSR bitmap in this case.
10642 *
10643 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10644 * each VM-entry, hence initializing it once per-VM while setting up the
10645 * nested-guest VMCS is not sufficient.
10646 */
10647 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10648 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10649 {
10650 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10651 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10652 Assert(pu64MsrBitmapNstGst);
10653 Assert(pu64MsrBitmapGst);
10654
10655 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10656 for (uint32_t i = 0; i < cFrags; i++)
10657 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10658 }
10659 else
10660 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10661}
10662
10663
10664/**
10665 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10666 * hardware-assisted VMX execution of the nested-guest.
10667 *
10668 * For a guest, we don't modify these controls once we set up the VMCS and hence
10669 * this function is never called.
10670 *
10671 * For nested-guests since the guest hypervisor provides these controls on every
10672 * nested-guest VM-entry and could potentially change them everytime we need to
10673 * merge them before every nested-guest VM-entry.
10674 *
10675 * @returns VBox status code.
10676 * @param pVCpu The cross context virtual CPU structure.
10677 */
10678static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10679{
10680 PVM pVM = pVCpu->CTX_SUFF(pVM);
10681 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10682 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10683 Assert(pVmcsNstGst);
10684
10685 /*
10686 * Merge the controls with the requirements of the guest VMCS.
10687 *
10688 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10689 * VMCS with the features supported by the physical CPU as it's already done by the
10690 * VMLAUNCH/VMRESUME instruction emulation.
10691 *
10692 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10693 * derived from the VMX features supported by the physical CPU.
10694 */
10695
10696 /* Pin-based VM-execution controls. */
10697 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10698
10699 /* Processor-based VM-execution controls. */
10700 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10701 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10702 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10703 | VMX_PROC_CTLS_USE_TPR_SHADOW
10704 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10705
10706 /* Secondary processor-based VM-execution controls. */
10707 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10708 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10709 | VMX_PROC_CTLS2_INVPCID
10710 | VMX_PROC_CTLS2_VMCS_SHADOWING
10711 | VMX_PROC_CTLS2_RDTSCP
10712 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10713 | VMX_PROC_CTLS2_APIC_REG_VIRT
10714 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10715 | VMX_PROC_CTLS2_VMFUNC));
10716
10717 /*
10718 * VM-entry controls:
10719 * These controls contains state that depends on the nested-guest state (primarily
10720 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10721 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10722 * properly continue executing the nested-guest if the EFER MSR changes but does not
10723 * cause a nested-guest VM-exits.
10724 *
10725 * VM-exit controls:
10726 * These controls specify the host state on return. We cannot use the controls from
10727 * the guest hypervisor state as is as it would contain the guest state rather than
10728 * the host state. Since the host state is subject to change (e.g. preemption, trips
10729 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10730 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10731 *
10732 * VM-entry MSR-load:
10733 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10734 * context by the VMLAUNCH/VMRESUME instruction emulation.
10735 *
10736 * VM-exit MSR-store:
10737 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10738 * back into the VM-exit MSR-store area.
10739 *
10740 * VM-exit MSR-load areas:
10741 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10742 * can entirely ignore what the guest hypervisor wants to load here.
10743 */
10744
10745 /*
10746 * Exception bitmap.
10747 *
10748 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10749 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10750 * code more flexible if intercepting exceptions become more dynamic in the future we do
10751 * it as part of exporting the nested-guest state.
10752 */
10753 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10754
10755 /*
10756 * CR0/CR4 guest/host mask.
10757 *
10758 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10759 * cause VM-exits, so we need to merge them here.
10760 */
10761 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10762 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10763
10764 /*
10765 * Page-fault error-code mask and match.
10766 *
10767 * Although we require unrestricted guest execution (and thereby nested-paging) for
10768 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10769 * normally intercept #PFs, it might intercept them for debugging purposes.
10770 *
10771 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10772 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10773 */
10774 uint32_t u32XcptPFMask;
10775 uint32_t u32XcptPFMatch;
10776 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10777 {
10778 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10779 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10780 }
10781 else
10782 {
10783 u32XcptPFMask = 0;
10784 u32XcptPFMatch = 0;
10785 }
10786
10787 /*
10788 * Pause-Loop exiting.
10789 */
10790 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10791 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10792
10793 /*
10794 * I/O Bitmap.
10795 *
10796 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10797 * intercept all I/O port accesses.
10798 */
10799 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10800
10801 /*
10802 * VMCS shadowing.
10803 *
10804 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10805 * enabled while executing the nested-guest.
10806 */
10807 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10808
10809 /*
10810 * APIC-access page.
10811 *
10812 * The APIC-access page address has already been initialized while setting up the
10813 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it should
10814 * not be of any consequence to the host or to the guest for that matter, but we only
10815 * accept valid addresses verified by the VMLAUNCH/VMRESUME instruction emulation to keep
10816 * it simple.
10817 */
10818
10819 /*
10820 * Virtual-APIC page and TPR threshold.
10821 *
10822 * The virtual-APIC page has already been allocated (by CPUM during VM startup) and cached
10823 * from guest memory as part of VMLAUNCH/VMRESUME instruction emulation. The host physical
10824 * address has also been updated in the nested-guest VMCS object during allocation.
10825 */
10826 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10827 RTHCPHYS HCPhysVirtApic;
10828 uint32_t u32TprThreshold;
10829 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10830 {
10831 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10832 HCPhysVirtApic = pVmcsInfoNstGst->HCPhysVirtApic;
10833 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10834 }
10835 else
10836 {
10837 HCPhysVirtApic = 0;
10838 u32TprThreshold = 0;
10839
10840 /*
10841 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10842 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10843 * be taken care of by EPT/shadow paging.
10844 */
10845 if (pVM->hm.s.fAllow64BitGuests)
10846 {
10847 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10848 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10849 }
10850 }
10851
10852 /*
10853 * Validate basic assumptions.
10854 */
10855 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10856 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10857 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10858
10859 /*
10860 * Commit it to the nested-guest VMCS.
10861 */
10862 int rc = VINF_SUCCESS;
10863 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10864 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10865 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10866 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10867 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10868 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10869 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10870 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10871 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10872 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10873 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10874 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10875 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10876 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10877 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10878 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10879 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10880 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10881 {
10882 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10883 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10884 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10885 }
10886 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10887 {
10888 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10889 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, pVmcsInfoNstGst->HCPhysVirtApic);
10890 }
10891 AssertRCReturn(rc, rc);
10892
10893 /*
10894 * Update the nested-guest VMCS cache.
10895 */
10896 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10897 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10898 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10899 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10900 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10901 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10902 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10903 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10904 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10905
10906 /*
10907 * MSR bitmap.
10908 *
10909 * The MSR bitmap address has already been initialized while setting up the nested-guest
10910 * VMCS, here we need to merge the MSR bitmaps.
10911 */
10912 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10913 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10914
10915 return VINF_SUCCESS;
10916}
10917#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10918
10919
10920/**
10921 * Does the preparations before executing guest code in VT-x.
10922 *
10923 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10924 * recompiler/IEM. We must be cautious what we do here regarding committing
10925 * guest-state information into the VMCS assuming we assuredly execute the
10926 * guest in VT-x mode.
10927 *
10928 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10929 * the common-state (TRPM/forceflags), we must undo those changes so that the
10930 * recompiler/IEM can (and should) use them when it resumes guest execution.
10931 * Otherwise such operations must be done when we can no longer exit to ring-3.
10932 *
10933 * @returns Strict VBox status code (i.e. informational status codes too).
10934 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10935 * have been disabled.
10936 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10937 * pending events).
10938 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10939 * double-fault into the guest.
10940 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10941 * dispatched directly.
10942 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10943 *
10944 * @param pVCpu The cross context virtual CPU structure.
10945 * @param pVmxTransient The VMX-transient structure.
10946 * @param fStepping Whether we are single-stepping the guest in the
10947 * hypervisor debugger. Makes us ignore some of the reasons
10948 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10949 * if event dispatching took place.
10950 */
10951static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10952{
10953 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10954
10955#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10956 if (pVmxTransient->fIsNestedGuest)
10957 {
10958 RT_NOREF2(pVCpu, fStepping);
10959 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10960 return VINF_EM_RESCHEDULE_REM;
10961 }
10962#endif
10963
10964#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10965 PGMRZDynMapFlushAutoSet(pVCpu);
10966#endif
10967
10968 /*
10969 * Check and process force flag actions, some of which might require us to go back to ring-3.
10970 */
10971 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10972 if (rcStrict == VINF_SUCCESS)
10973 { /* FFs don't get set all the time. */ }
10974 else
10975 return rcStrict;
10976
10977 /*
10978 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10979 */
10980 /** @todo Doing this from ring-3 after VM setup phase causes a
10981 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10982 * idea why atm. */
10983 PVM pVM = pVCpu->CTX_SUFF(pVM);
10984 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10985 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10986 && PDMHasApic(pVM))
10987 {
10988 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10989 AssertRCReturn(rc, rc);
10990 }
10991
10992#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10993 /*
10994 * Merge guest VMCS controls with the nested-guest VMCS controls.
10995 *
10996 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10997 * saved state), we should be okay with merging controls as we initialize the
10998 * guest VMCS controls as part of VM setup phase.
10999 */
11000 if ( pVmxTransient->fIsNestedGuest
11001 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
11002 {
11003 int rc = hmR0VmxMergeVmcsNested(pVCpu);
11004 AssertRCReturn(rc, rc);
11005 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
11006 }
11007#endif
11008
11009 /*
11010 * Evaluate events to be injected into the guest.
11011 *
11012 * Events in TRPM can be injected without inspecting the guest state.
11013 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11014 * guest to cause a VM-exit the next time they are ready to receive the event.
11015 *
11016 * With nested-guests, evaluating pending events may cause VM-exits.
11017 */
11018 if (TRPMHasTrap(pVCpu))
11019 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11020
11021 uint32_t fIntrState;
11022 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11023
11024#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11025 /*
11026 * While evaluating pending events if something failed (unlikely) or if we were
11027 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11028 */
11029 if (rcStrict != VINF_SUCCESS)
11030 return rcStrict;
11031 if ( pVmxTransient->fIsNestedGuest
11032 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11033 {
11034 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11035 return VINF_VMX_VMEXIT;
11036 }
11037#else
11038 Assert(rcStrict == VINF_SUCCESS);
11039#endif
11040
11041 /*
11042 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11043 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11044 * also result in triple-faulting the VM.
11045 *
11046 * With nested-guests, the above does not apply since unrestricted guest execution is a
11047 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11048 */
11049 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11050 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11051 { /* likely */ }
11052 else
11053 {
11054 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11055 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11056 return rcStrict;
11057 }
11058
11059 /*
11060 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11061 * import CR3 themselves. We will need to update them here, as even as late as the above
11062 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11063 * the below force flags to be set.
11064 */
11065 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11066 {
11067 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11068 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11069 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11070 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11071 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11072 }
11073 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11074 {
11075 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11076 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11077 }
11078
11079#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11080 /* Paranoia. */
11081 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11082#endif
11083
11084 /*
11085 * No longjmps to ring-3 from this point on!!!
11086 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11087 * This also disables flushing of the R0-logger instance (if any).
11088 */
11089 VMMRZCallRing3Disable(pVCpu);
11090
11091 /*
11092 * Export the guest state bits.
11093 *
11094 * We cannot perform longjmps while loading the guest state because we do not preserve the
11095 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11096 * CPU migration.
11097 *
11098 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11099 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11100 */
11101 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11102 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11103 { /* likely */ }
11104 else
11105 {
11106 VMMRZCallRing3Enable(pVCpu);
11107 return rcStrict;
11108 }
11109
11110 /*
11111 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11112 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11113 * preemption disabled for a while. Since this is purely to aid the
11114 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11115 * disable interrupt on NT.
11116 *
11117 * We need to check for force-flags that could've possible been altered since we last
11118 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11119 * see @bugref{6398}).
11120 *
11121 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11122 * to ring-3 before executing guest code.
11123 */
11124 pVmxTransient->fEFlags = ASMIntDisableFlags();
11125
11126 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11127 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11128 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11129 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11130 {
11131 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11132 {
11133#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11134 /*
11135 * If we are executing a nested-guest make sure that we should intercept subsequent
11136 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
11137 * the VM-exit instruction emulation happy.
11138 */
11139 if (pVmxTransient->fIsNestedGuest)
11140 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11141#endif
11142
11143 /*
11144 * We've injected any pending events. This is really the point of no return (to ring-3).
11145 *
11146 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11147 * returns from this function, so do -not- enable them here.
11148 */
11149 pVCpu->hm.s.Event.fPending = false;
11150 return VINF_SUCCESS;
11151 }
11152
11153 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11154 rcStrict = VINF_EM_RAW_INTERRUPT;
11155 }
11156 else
11157 {
11158 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11159 rcStrict = VINF_EM_RAW_TO_R3;
11160 }
11161
11162 ASMSetFlags(pVmxTransient->fEFlags);
11163 VMMRZCallRing3Enable(pVCpu);
11164
11165 return rcStrict;
11166}
11167
11168
11169/**
11170 * Final preparations before executing guest code using hardware-assisted VMX.
11171 *
11172 * We can no longer get preempted to a different host CPU and there are no returns
11173 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11174 * failures), this function is not intended to fail sans unrecoverable hardware
11175 * errors.
11176 *
11177 * @param pVCpu The cross context virtual CPU structure.
11178 * @param pVmxTransient The VMX-transient structure.
11179 *
11180 * @remarks Called with preemption disabled.
11181 * @remarks No-long-jump zone!!!
11182 */
11183static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11184{
11185 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11186 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11187 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11188 Assert(!pVCpu->hm.s.Event.fPending);
11189
11190 /*
11191 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11192 */
11193 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11194 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11195
11196 PVM pVM = pVCpu->CTX_SUFF(pVM);
11197 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11198 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11199 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11200
11201 if (!CPUMIsGuestFPUStateActive(pVCpu))
11202 {
11203 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11204 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11205 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11206 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11207 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11208 }
11209
11210 /*
11211 * Re-export the host state bits as we may've been preempted (only happens when
11212 * thread-context hooks are used or when the VM start function changes) or if
11213 * the host CR0 is modified while loading the guest FPU state above.
11214 *
11215 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11216 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11217 * see @bugref{8432}.
11218 *
11219 * This may also happen when switching to/from a nested-guest VMCS without leaving
11220 * ring-0.
11221 */
11222 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11223 {
11224 hmR0VmxExportHostState(pVCpu);
11225 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11226 }
11227 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11228
11229 /*
11230 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11231 */
11232 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11233 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11234 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11235
11236 /*
11237 * Store status of the shared guest/host debug state at the time of VM-entry.
11238 */
11239#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11240 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11241 {
11242 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11243 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11244 }
11245 else
11246#endif
11247 {
11248 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11249 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11250 }
11251
11252 /*
11253 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11254 * more than one conditional check. The post-run side of our code shall determine
11255 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11256 */
11257 if (pVmcsInfo->pbVirtApic)
11258 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11259
11260 /*
11261 * Update the host MSRs values in the VM-exit MSR-load area.
11262 */
11263 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11264 {
11265 if (pVmcsInfo->cExitMsrLoad > 0)
11266 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11267 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11268 }
11269
11270 /*
11271 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11272 * VMX-preemption timer based on the next virtual sync clock deadline.
11273 */
11274 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11275 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11276 {
11277 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11278 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11279 }
11280
11281 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11282 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11283 if (!fIsRdtscIntercepted)
11284 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11285 else
11286 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11287
11288 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11289 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11290 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11291 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11292 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11293
11294 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11295
11296 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11297 as we're about to start executing the guest . */
11298
11299 /*
11300 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11301 *
11302 * This is done this late as updating the TSC offsetting/preemption timer above
11303 * figures out if we can skip intercepting RDTSCP by calculating the number of
11304 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11305 */
11306 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11307 && !fIsRdtscIntercepted)
11308 {
11309 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11310
11311 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11312 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11313 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11314 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11315 AssertRC(rc);
11316 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11317 pVmxTransient->fRemoveTscAuxMsr = true;
11318 }
11319
11320#ifdef VBOX_STRICT
11321 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11322 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11323 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11324 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11325#endif
11326
11327#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11328 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11329 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11330 * see @bugref{9180#c54}. */
11331 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11332 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11333 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11334#endif
11335}
11336
11337
11338/**
11339 * First C routine invoked after running guest code using hardware-assisted VMX.
11340 *
11341 * @param pVCpu The cross context virtual CPU structure.
11342 * @param pVmxTransient The VMX-transient structure.
11343 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11344 *
11345 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11346 *
11347 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11348 * unconditionally when it is safe to do so.
11349 */
11350static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11351{
11352 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11353
11354 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11355 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11356 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11357 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11358 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11359 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11360
11361 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11362 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11363 {
11364 uint64_t uGstTsc;
11365 if (!pVmxTransient->fIsNestedGuest)
11366 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11367 else
11368 {
11369 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11370 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11371 }
11372 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11373 }
11374
11375 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11376 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11377 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11378
11379#if HC_ARCH_BITS == 64
11380 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11381#endif
11382#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11383 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11384 and we need to leave it alone here. */
11385 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11386 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11387#else
11388 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11389#endif
11390#ifdef VBOX_STRICT
11391 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11392#endif
11393 Assert(!ASMIntAreEnabled());
11394 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11395 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11396
11397#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11398 /*
11399 * Clean all the VMCS fields in the transient structure before reading
11400 * anything from the VMCS.
11401 */
11402 pVmxTransient->uExitReason = 0;
11403 pVmxTransient->uExitIntErrorCode = 0;
11404 pVmxTransient->uExitQual = 0;
11405 pVmxTransient->uGuestLinearAddr = 0;
11406 pVmxTransient->uExitIntInfo = 0;
11407 pVmxTransient->cbInstr = 0;
11408 pVmxTransient->ExitInstrInfo.u = 0;
11409 pVmxTransient->uEntryIntInfo = 0;
11410 pVmxTransient->uEntryXcptErrorCode = 0;
11411 pVmxTransient->cbEntryInstr = 0;
11412 pVmxTransient->uIdtVectoringInfo = 0;
11413 pVmxTransient->uIdtVectoringErrorCode = 0;
11414#endif
11415
11416 /*
11417 * Save the basic VM-exit reason and check if the VM-entry failed.
11418 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11419 */
11420 uint32_t uExitReason;
11421 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11422 AssertRC(rc);
11423 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11424 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11425
11426 /*
11427 * Log the VM-exit before logging anything else as otherwise it might be a
11428 * tad confusing what happens before and after the world-switch.
11429 */
11430 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11431
11432 /*
11433 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11434 * bitmap permissions, if it was added before VM-entry.
11435 */
11436 if (pVmxTransient->fRemoveTscAuxMsr)
11437 {
11438 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11439 pVmxTransient->fRemoveTscAuxMsr = false;
11440 }
11441
11442 /*
11443 * Check if VMLAUNCH/VMRESUME succeeded.
11444 * If this failed, we cause a guru meditation and cease further execution.
11445 *
11446 * However, if we are executing a nested-guest we might fail if we use the
11447 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11448 */
11449 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11450 {
11451 /*
11452 * Update the VM-exit history array here even if the VM-entry failed due to:
11453 * - Invalid guest state.
11454 * - MSR loading.
11455 * - Machine-check event.
11456 *
11457 * In any of the above cases we will still have a "valid" VM-exit reason
11458 * despite @a fVMEntryFailed being false.
11459 *
11460 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11461 *
11462 * Note! We don't have CS or RIP at this point. Will probably address that later
11463 * by amending the history entry added here.
11464 */
11465 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11466 UINT64_MAX, uHostTsc);
11467
11468 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11469 {
11470 VMMRZCallRing3Enable(pVCpu);
11471
11472 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11473 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11474
11475#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11476 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11477 AssertRC(rc);
11478#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11479 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11480 AssertRC(rc);
11481#else
11482 /*
11483 * Import the guest-interruptibility state always as we need it while evaluating
11484 * injecting events on re-entry.
11485 *
11486 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11487 * checking for real-mode while exporting the state because all bits that cause
11488 * mode changes wrt CR0 are intercepted.
11489 */
11490 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11491 AssertRC(rc);
11492#endif
11493
11494 /*
11495 * Sync the TPR shadow with our APIC state.
11496 *
11497 * With nested-guests, mark the virtual-APIC page as dirty so it can be synced
11498 * when performing the nested-guest VM-exit.
11499 */
11500 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11501 {
11502 if (!pVmxTransient->fIsNestedGuest)
11503 {
11504 Assert(pVmcsInfo->pbVirtApic);
11505 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11506 {
11507 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11508 AssertRC(rc);
11509 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11510 }
11511 }
11512 else
11513 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true;
11514 }
11515
11516 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11517 return;
11518 }
11519 }
11520#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11521 else if (pVmxTransient->fIsNestedGuest)
11522 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11523#endif
11524 else
11525 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11526
11527 VMMRZCallRing3Enable(pVCpu);
11528}
11529
11530
11531/**
11532 * Runs the guest code using hardware-assisted VMX the normal way.
11533 *
11534 * @returns VBox status code.
11535 * @param pVCpu The cross context virtual CPU structure.
11536 * @param pcLoops Pointer to the number of executed loops.
11537 */
11538static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11539{
11540 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11541 Assert(pcLoops);
11542 Assert(*pcLoops <= cMaxResumeLoops);
11543 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11544
11545#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11546 /*
11547 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11548 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11549 * guest VMCS while entering the VMX ring-0 session.
11550 */
11551 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11552 {
11553 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11554 if (RT_SUCCESS(rc))
11555 { /* likely */ }
11556 else
11557 {
11558 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11559 return rc;
11560 }
11561 }
11562#endif
11563
11564 VMXTRANSIENT VmxTransient;
11565 RT_ZERO(VmxTransient);
11566 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11567
11568 /* Paranoia. */
11569 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11570
11571 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11572 for (;;)
11573 {
11574 Assert(!HMR0SuspendPending());
11575 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11576 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11577
11578 /*
11579 * Preparatory work for running nested-guest code, this may force us to
11580 * return to ring-3.
11581 *
11582 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11583 */
11584 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11585 if (rcStrict != VINF_SUCCESS)
11586 break;
11587
11588 /* Interrupts are disabled at this point! */
11589 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11590 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11591 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11592 /* Interrupts are re-enabled at this point! */
11593
11594 /*
11595 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11596 */
11597 if (RT_SUCCESS(rcRun))
11598 { /* very likely */ }
11599 else
11600 {
11601 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11602 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11603 return rcRun;
11604 }
11605
11606 /*
11607 * Profile the VM-exit.
11608 */
11609 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11610 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11611 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11612 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11613 HMVMX_START_EXIT_DISPATCH_PROF();
11614
11615 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11616
11617 /*
11618 * Handle the VM-exit.
11619 */
11620#ifdef HMVMX_USE_FUNCTION_TABLE
11621 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11622#else
11623 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11624#endif
11625 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11626 if (rcStrict == VINF_SUCCESS)
11627 {
11628 if (++(*pcLoops) <= cMaxResumeLoops)
11629 continue;
11630 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11631 rcStrict = VINF_EM_RAW_INTERRUPT;
11632 }
11633 break;
11634 }
11635
11636 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11637 return rcStrict;
11638}
11639
11640
11641#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11642/**
11643 * Runs the nested-guest code using hardware-assisted VMX.
11644 *
11645 * @returns VBox status code.
11646 * @param pVCpu The cross context virtual CPU structure.
11647 * @param pcLoops Pointer to the number of executed loops.
11648 *
11649 * @sa hmR0VmxRunGuestCodeNormal.
11650 */
11651static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11652{
11653 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11654 Assert(pcLoops);
11655 Assert(*pcLoops <= cMaxResumeLoops);
11656 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11657
11658 /*
11659 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11660 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11661 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11662 */
11663 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11664 {
11665 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11666 if (RT_SUCCESS(rc))
11667 { /* likely */ }
11668 else
11669 {
11670 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11671 return rc;
11672 }
11673 }
11674
11675 VMXTRANSIENT VmxTransient;
11676 RT_ZERO(VmxTransient);
11677 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11678 VmxTransient.fIsNestedGuest = true;
11679
11680 /* Paranoia. */
11681 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11682
11683 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11684 for (;;)
11685 {
11686 Assert(!HMR0SuspendPending());
11687 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11688 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11689
11690 /*
11691 * Preparatory work for running guest code, this may force us to
11692 * return to ring-3.
11693 *
11694 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11695 */
11696 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11697 if (rcStrict != VINF_SUCCESS)
11698 break;
11699
11700 /* Interrupts are disabled at this point! */
11701 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11702 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11703 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11704 /* Interrupts are re-enabled at this point! */
11705
11706 /*
11707 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11708 */
11709 if (RT_SUCCESS(rcRun))
11710 { /* very likely */ }
11711 else
11712 {
11713 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11714 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11715 return rcRun;
11716 }
11717
11718 /*
11719 * Profile the VM-exit.
11720 */
11721 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11722 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11723 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11724 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11725 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11726 HMVMX_START_EXIT_DISPATCH_PROF();
11727
11728 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11729
11730 /*
11731 * Handle the VM-exit.
11732 */
11733 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11734 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11735 if (rcStrict == VINF_SUCCESS)
11736 {
11737 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11738 {
11739 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11740 rcStrict = VINF_VMX_VMEXIT;
11741 }
11742 else
11743 {
11744 if (++(*pcLoops) <= cMaxResumeLoops)
11745 continue;
11746 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11747 rcStrict = VINF_EM_RAW_INTERRUPT;
11748 }
11749 }
11750 else
11751 Assert(rcStrict != VINF_VMX_VMEXIT);
11752 break;
11753 }
11754
11755 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11756 return rcStrict;
11757}
11758#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11759
11760
11761/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11762 * probes.
11763 *
11764 * The following few functions and associated structure contains the bloat
11765 * necessary for providing detailed debug events and dtrace probes as well as
11766 * reliable host side single stepping. This works on the principle of
11767 * "subclassing" the normal execution loop and workers. We replace the loop
11768 * method completely and override selected helpers to add necessary adjustments
11769 * to their core operation.
11770 *
11771 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11772 * any performance for debug and analysis features.
11773 *
11774 * @{
11775 */
11776
11777/**
11778 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11779 * the debug run loop.
11780 */
11781typedef struct VMXRUNDBGSTATE
11782{
11783 /** The RIP we started executing at. This is for detecting that we stepped. */
11784 uint64_t uRipStart;
11785 /** The CS we started executing with. */
11786 uint16_t uCsStart;
11787
11788 /** Whether we've actually modified the 1st execution control field. */
11789 bool fModifiedProcCtls : 1;
11790 /** Whether we've actually modified the 2nd execution control field. */
11791 bool fModifiedProcCtls2 : 1;
11792 /** Whether we've actually modified the exception bitmap. */
11793 bool fModifiedXcptBitmap : 1;
11794
11795 /** We desire the modified the CR0 mask to be cleared. */
11796 bool fClearCr0Mask : 1;
11797 /** We desire the modified the CR4 mask to be cleared. */
11798 bool fClearCr4Mask : 1;
11799 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11800 uint32_t fCpe1Extra;
11801 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11802 uint32_t fCpe1Unwanted;
11803 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11804 uint32_t fCpe2Extra;
11805 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11806 uint32_t bmXcptExtra;
11807 /** The sequence number of the Dtrace provider settings the state was
11808 * configured against. */
11809 uint32_t uDtraceSettingsSeqNo;
11810 /** VM-exits to check (one bit per VM-exit). */
11811 uint32_t bmExitsToCheck[3];
11812
11813 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11814 uint32_t fProcCtlsInitial;
11815 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11816 uint32_t fProcCtls2Initial;
11817 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11818 uint32_t bmXcptInitial;
11819} VMXRUNDBGSTATE;
11820AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11821typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11822
11823
11824/**
11825 * Initializes the VMXRUNDBGSTATE structure.
11826 *
11827 * @param pVCpu The cross context virtual CPU structure of the
11828 * calling EMT.
11829 * @param pVmxTransient The VMX-transient structure.
11830 * @param pDbgState The debug state to initialize.
11831 */
11832static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11833{
11834 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11835 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11836
11837 pDbgState->fModifiedProcCtls = false;
11838 pDbgState->fModifiedProcCtls2 = false;
11839 pDbgState->fModifiedXcptBitmap = false;
11840 pDbgState->fClearCr0Mask = false;
11841 pDbgState->fClearCr4Mask = false;
11842 pDbgState->fCpe1Extra = 0;
11843 pDbgState->fCpe1Unwanted = 0;
11844 pDbgState->fCpe2Extra = 0;
11845 pDbgState->bmXcptExtra = 0;
11846 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11847 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11848 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11849}
11850
11851
11852/**
11853 * Updates the VMSC fields with changes requested by @a pDbgState.
11854 *
11855 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11856 * immediately before executing guest code, i.e. when interrupts are disabled.
11857 * We don't check status codes here as we cannot easily assert or return in the
11858 * latter case.
11859 *
11860 * @param pVCpu The cross context virtual CPU structure.
11861 * @param pVmxTransient The VMX-transient structure.
11862 * @param pDbgState The debug state.
11863 */
11864static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11865{
11866 /*
11867 * Ensure desired flags in VMCS control fields are set.
11868 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11869 *
11870 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11871 * there should be no stale data in pCtx at this point.
11872 */
11873 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11874 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11875 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11876 {
11877 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11878 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11879 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11880 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11881 pDbgState->fModifiedProcCtls = true;
11882 }
11883
11884 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11885 {
11886 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11887 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11888 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11889 pDbgState->fModifiedProcCtls2 = true;
11890 }
11891
11892 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11893 {
11894 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11895 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11896 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11897 pDbgState->fModifiedXcptBitmap = true;
11898 }
11899
11900 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11901 {
11902 pVmcsInfo->u64Cr0Mask = 0;
11903 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11904 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11905 }
11906
11907 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11908 {
11909 pVmcsInfo->u64Cr4Mask = 0;
11910 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11911 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11912 }
11913
11914 NOREF(pVCpu);
11915}
11916
11917
11918/**
11919 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11920 * re-entry next time around.
11921 *
11922 * @returns Strict VBox status code (i.e. informational status codes too).
11923 * @param pVCpu The cross context virtual CPU structure.
11924 * @param pVmxTransient The VMX-transient structure.
11925 * @param pDbgState The debug state.
11926 * @param rcStrict The return code from executing the guest using single
11927 * stepping.
11928 */
11929static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11930 VBOXSTRICTRC rcStrict)
11931{
11932 /*
11933 * Restore VM-exit control settings as we may not reenter this function the
11934 * next time around.
11935 */
11936 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11937
11938 /* We reload the initial value, trigger what we can of recalculations the
11939 next time around. From the looks of things, that's all that's required atm. */
11940 if (pDbgState->fModifiedProcCtls)
11941 {
11942 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11943 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11944 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11945 AssertRCReturn(rc2, rc2);
11946 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11947 }
11948
11949 /* We're currently the only ones messing with this one, so just restore the
11950 cached value and reload the field. */
11951 if ( pDbgState->fModifiedProcCtls2
11952 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11953 {
11954 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11955 AssertRCReturn(rc2, rc2);
11956 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11957 }
11958
11959 /* If we've modified the exception bitmap, we restore it and trigger
11960 reloading and partial recalculation the next time around. */
11961 if (pDbgState->fModifiedXcptBitmap)
11962 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11963
11964 return rcStrict;
11965}
11966
11967
11968/**
11969 * Configures VM-exit controls for current DBGF and DTrace settings.
11970 *
11971 * This updates @a pDbgState and the VMCS execution control fields to reflect
11972 * the necessary VM-exits demanded by DBGF and DTrace.
11973 *
11974 * @param pVCpu The cross context virtual CPU structure.
11975 * @param pVmxTransient The VMX-transient structure. May update
11976 * fUpdatedTscOffsettingAndPreemptTimer.
11977 * @param pDbgState The debug state.
11978 */
11979static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11980{
11981 /*
11982 * Take down the dtrace serial number so we can spot changes.
11983 */
11984 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11985 ASMCompilerBarrier();
11986
11987 /*
11988 * We'll rebuild most of the middle block of data members (holding the
11989 * current settings) as we go along here, so start by clearing it all.
11990 */
11991 pDbgState->bmXcptExtra = 0;
11992 pDbgState->fCpe1Extra = 0;
11993 pDbgState->fCpe1Unwanted = 0;
11994 pDbgState->fCpe2Extra = 0;
11995 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11996 pDbgState->bmExitsToCheck[i] = 0;
11997
11998 /*
11999 * Software interrupts (INT XXh) - no idea how to trigger these...
12000 */
12001 PVM pVM = pVCpu->CTX_SUFF(pVM);
12002 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
12003 || VBOXVMM_INT_SOFTWARE_ENABLED())
12004 {
12005 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12006 }
12007
12008 /*
12009 * INT3 breakpoints - triggered by #BP exceptions.
12010 */
12011 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
12012 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12013
12014 /*
12015 * Exception bitmap and XCPT events+probes.
12016 */
12017 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
12018 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
12019 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
12020
12021 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
12022 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
12023 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12024 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
12025 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
12026 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
12027 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12028 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12029 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12030 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12031 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12032 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12033 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12034 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12035 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12036 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12037 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12038 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12039
12040 if (pDbgState->bmXcptExtra)
12041 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12042
12043 /*
12044 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12045 *
12046 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12047 * So, when adding/changing/removing please don't forget to update it.
12048 *
12049 * Some of the macros are picking up local variables to save horizontal space,
12050 * (being able to see it in a table is the lesser evil here).
12051 */
12052#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12053 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12054 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12055#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12056 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12057 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12058 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12059 } else do { } while (0)
12060#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12061 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12062 { \
12063 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12064 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12065 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12066 } else do { } while (0)
12067#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12068 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12069 { \
12070 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12071 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12072 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12073 } else do { } while (0)
12074#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12075 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12076 { \
12077 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12078 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12079 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12080 } else do { } while (0)
12081
12082 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12083 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12084 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12085 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12086 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12087
12088 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12089 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12090 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12091 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12092 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12093 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12094 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12095 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12096 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12097 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12098 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12099 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12100 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12101 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12102 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12103 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12104 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12105 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12106 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12107 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12108 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12109 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12110 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12111 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12112 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12113 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12114 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12115 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12116 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12117 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12118 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12119 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12120 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12121 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12122 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12123 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12124
12125 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12126 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12127 {
12128 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12129 | CPUMCTX_EXTRN_APIC_TPR);
12130 AssertRC(rc);
12131
12132#if 0 /** @todo fix me */
12133 pDbgState->fClearCr0Mask = true;
12134 pDbgState->fClearCr4Mask = true;
12135#endif
12136 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12137 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12138 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12139 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12140 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12141 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12142 require clearing here and in the loop if we start using it. */
12143 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12144 }
12145 else
12146 {
12147 if (pDbgState->fClearCr0Mask)
12148 {
12149 pDbgState->fClearCr0Mask = false;
12150 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12151 }
12152 if (pDbgState->fClearCr4Mask)
12153 {
12154 pDbgState->fClearCr4Mask = false;
12155 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12156 }
12157 }
12158 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12159 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12160
12161 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12162 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12163 {
12164 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12165 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12166 }
12167 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12168 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12169
12170 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12171 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12172 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12173 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12174 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12175 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12176 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12177 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12178#if 0 /** @todo too slow, fix handler. */
12179 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12180#endif
12181 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12182
12183 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12184 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12185 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12186 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12187 {
12188 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12189 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12190 }
12191 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12192 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12193 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12194 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12195
12196 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12197 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12198 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12199 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12200 {
12201 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12202 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12203 }
12204 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12205 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12206 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12207 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12208
12209 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12210 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12211 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12212 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12213 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12214 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12215 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12216 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12217 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12218 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12219 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12220 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12221 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12222 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12223 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12224 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12225 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12226 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12227 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12228 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12229 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12230 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12231
12232#undef IS_EITHER_ENABLED
12233#undef SET_ONLY_XBM_IF_EITHER_EN
12234#undef SET_CPE1_XBM_IF_EITHER_EN
12235#undef SET_CPEU_XBM_IF_EITHER_EN
12236#undef SET_CPE2_XBM_IF_EITHER_EN
12237
12238 /*
12239 * Sanitize the control stuff.
12240 */
12241 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12242 if (pDbgState->fCpe2Extra)
12243 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12244 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12245 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12246 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12247 {
12248 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12249 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12250 }
12251
12252 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12253 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12254 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12255 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12256}
12257
12258
12259/**
12260 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12261 * appropriate.
12262 *
12263 * The caller has checked the VM-exit against the
12264 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12265 * already, so we don't have to do that either.
12266 *
12267 * @returns Strict VBox status code (i.e. informational status codes too).
12268 * @param pVCpu The cross context virtual CPU structure.
12269 * @param pVmxTransient The VMX-transient structure.
12270 * @param uExitReason The VM-exit reason.
12271 *
12272 * @remarks The name of this function is displayed by dtrace, so keep it short
12273 * and to the point. No longer than 33 chars long, please.
12274 */
12275static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12276{
12277 /*
12278 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12279 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12280 *
12281 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12282 * does. Must add/change/remove both places. Same ordering, please.
12283 *
12284 * Added/removed events must also be reflected in the next section
12285 * where we dispatch dtrace events.
12286 */
12287 bool fDtrace1 = false;
12288 bool fDtrace2 = false;
12289 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12290 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12291 uint32_t uEventArg = 0;
12292#define SET_EXIT(a_EventSubName) \
12293 do { \
12294 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12295 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12296 } while (0)
12297#define SET_BOTH(a_EventSubName) \
12298 do { \
12299 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12300 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12301 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12302 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12303 } while (0)
12304 switch (uExitReason)
12305 {
12306 case VMX_EXIT_MTF:
12307 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12308
12309 case VMX_EXIT_XCPT_OR_NMI:
12310 {
12311 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12312 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12313 {
12314 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12315 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12316 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12317 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12318 {
12319 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12320 {
12321 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12322 uEventArg = pVmxTransient->uExitIntErrorCode;
12323 }
12324 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12325 switch (enmEvent1)
12326 {
12327 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12328 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12329 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12330 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12331 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12332 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12333 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12334 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12335 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12336 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12337 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12338 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12339 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12340 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12341 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12342 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12343 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12344 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12345 default: break;
12346 }
12347 }
12348 else
12349 AssertFailed();
12350 break;
12351
12352 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12353 uEventArg = idxVector;
12354 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12355 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12356 break;
12357 }
12358 break;
12359 }
12360
12361 case VMX_EXIT_TRIPLE_FAULT:
12362 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12363 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12364 break;
12365 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12366 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12367 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12368 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12369 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12370
12371 /* Instruction specific VM-exits: */
12372 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12373 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12374 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12375 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12376 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12377 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12378 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12379 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12380 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12381 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12382 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12383 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12384 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12385 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12386 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12387 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12388 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12389 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12390 case VMX_EXIT_MOV_CRX:
12391 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12392 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12393 SET_BOTH(CRX_READ);
12394 else
12395 SET_BOTH(CRX_WRITE);
12396 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12397 break;
12398 case VMX_EXIT_MOV_DRX:
12399 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12400 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12401 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12402 SET_BOTH(DRX_READ);
12403 else
12404 SET_BOTH(DRX_WRITE);
12405 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12406 break;
12407 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12408 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12409 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12410 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12411 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12412 case VMX_EXIT_GDTR_IDTR_ACCESS:
12413 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12414 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12415 {
12416 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12417 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12418 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12419 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12420 }
12421 break;
12422
12423 case VMX_EXIT_LDTR_TR_ACCESS:
12424 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12425 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12426 {
12427 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12428 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12429 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12430 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12431 }
12432 break;
12433
12434 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12435 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12436 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12437 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12438 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12439 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12440 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12441 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12442 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12443 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12444 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12445
12446 /* Events that aren't relevant at this point. */
12447 case VMX_EXIT_EXT_INT:
12448 case VMX_EXIT_INT_WINDOW:
12449 case VMX_EXIT_NMI_WINDOW:
12450 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12451 case VMX_EXIT_PREEMPT_TIMER:
12452 case VMX_EXIT_IO_INSTR:
12453 break;
12454
12455 /* Errors and unexpected events. */
12456 case VMX_EXIT_INIT_SIGNAL:
12457 case VMX_EXIT_SIPI:
12458 case VMX_EXIT_IO_SMI:
12459 case VMX_EXIT_SMI:
12460 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12461 case VMX_EXIT_ERR_MSR_LOAD:
12462 case VMX_EXIT_ERR_MACHINE_CHECK:
12463 case VMX_EXIT_PML_FULL:
12464 case VMX_EXIT_VIRTUALIZED_EOI:
12465 break;
12466
12467 default:
12468 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12469 break;
12470 }
12471#undef SET_BOTH
12472#undef SET_EXIT
12473
12474 /*
12475 * Dtrace tracepoints go first. We do them here at once so we don't
12476 * have to copy the guest state saving and stuff a few dozen times.
12477 * Down side is that we've got to repeat the switch, though this time
12478 * we use enmEvent since the probes are a subset of what DBGF does.
12479 */
12480 if (fDtrace1 || fDtrace2)
12481 {
12482 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12483 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12484 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12485 switch (enmEvent1)
12486 {
12487 /** @todo consider which extra parameters would be helpful for each probe. */
12488 case DBGFEVENT_END: break;
12489 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12490 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12491 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12492 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12493 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12494 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12495 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12496 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12497 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12498 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12499 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12500 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12501 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12502 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12503 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12504 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12505 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12506 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12507 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12508 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12509 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12510 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12511 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12512 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12513 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12514 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12515 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12516 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12517 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12518 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12519 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12520 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12521 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12522 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12523 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12524 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12525 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12526 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12527 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12528 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12529 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12530 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12531 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12532 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12533 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12534 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12535 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12536 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12537 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12538 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12539 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12540 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12541 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12542 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12543 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12544 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12545 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12546 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12547 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12548 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12549 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12550 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12551 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12552 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12553 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12554 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12555 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12556 }
12557 switch (enmEvent2)
12558 {
12559 /** @todo consider which extra parameters would be helpful for each probe. */
12560 case DBGFEVENT_END: break;
12561 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12562 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12563 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12564 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12565 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12566 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12567 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12568 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12569 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12570 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12571 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12572 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12573 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12574 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12575 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12576 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12577 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12578 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12579 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12580 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12581 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12582 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12583 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12584 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12585 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12586 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12587 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12588 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12589 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12590 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12591 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12592 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12593 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12594 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12595 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12596 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12597 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12598 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12599 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12600 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12601 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12602 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12603 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12604 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12605 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12606 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12607 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12608 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12609 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12610 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12611 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12612 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12613 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12614 }
12615 }
12616
12617 /*
12618 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12619 * the DBGF call will do a full check).
12620 *
12621 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12622 * Note! If we have to events, we prioritize the first, i.e. the instruction
12623 * one, in order to avoid event nesting.
12624 */
12625 PVM pVM = pVCpu->CTX_SUFF(pVM);
12626 if ( enmEvent1 != DBGFEVENT_END
12627 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12628 {
12629 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12630 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12631 if (rcStrict != VINF_SUCCESS)
12632 return rcStrict;
12633 }
12634 else if ( enmEvent2 != DBGFEVENT_END
12635 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12636 {
12637 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12638 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12639 if (rcStrict != VINF_SUCCESS)
12640 return rcStrict;
12641 }
12642
12643 return VINF_SUCCESS;
12644}
12645
12646
12647/**
12648 * Single-stepping VM-exit filtering.
12649 *
12650 * This is preprocessing the VM-exits and deciding whether we've gotten far
12651 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12652 * handling is performed.
12653 *
12654 * @returns Strict VBox status code (i.e. informational status codes too).
12655 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12656 * @param pVmxTransient The VMX-transient structure.
12657 * @param pDbgState The debug state.
12658 */
12659DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12660{
12661 /*
12662 * Expensive (saves context) generic dtrace VM-exit probe.
12663 */
12664 uint32_t const uExitReason = pVmxTransient->uExitReason;
12665 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12666 { /* more likely */ }
12667 else
12668 {
12669 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12670 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12671 AssertRC(rc);
12672 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12673 }
12674
12675 /*
12676 * Check for host NMI, just to get that out of the way.
12677 */
12678 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12679 { /* normally likely */ }
12680 else
12681 {
12682 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12683 AssertRCReturn(rc2, rc2);
12684 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12685 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12686 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12687 }
12688
12689 /*
12690 * Check for single stepping event if we're stepping.
12691 */
12692 if (pVCpu->hm.s.fSingleInstruction)
12693 {
12694 switch (uExitReason)
12695 {
12696 case VMX_EXIT_MTF:
12697 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12698
12699 /* Various events: */
12700 case VMX_EXIT_XCPT_OR_NMI:
12701 case VMX_EXIT_EXT_INT:
12702 case VMX_EXIT_TRIPLE_FAULT:
12703 case VMX_EXIT_INT_WINDOW:
12704 case VMX_EXIT_NMI_WINDOW:
12705 case VMX_EXIT_TASK_SWITCH:
12706 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12707 case VMX_EXIT_APIC_ACCESS:
12708 case VMX_EXIT_EPT_VIOLATION:
12709 case VMX_EXIT_EPT_MISCONFIG:
12710 case VMX_EXIT_PREEMPT_TIMER:
12711
12712 /* Instruction specific VM-exits: */
12713 case VMX_EXIT_CPUID:
12714 case VMX_EXIT_GETSEC:
12715 case VMX_EXIT_HLT:
12716 case VMX_EXIT_INVD:
12717 case VMX_EXIT_INVLPG:
12718 case VMX_EXIT_RDPMC:
12719 case VMX_EXIT_RDTSC:
12720 case VMX_EXIT_RSM:
12721 case VMX_EXIT_VMCALL:
12722 case VMX_EXIT_VMCLEAR:
12723 case VMX_EXIT_VMLAUNCH:
12724 case VMX_EXIT_VMPTRLD:
12725 case VMX_EXIT_VMPTRST:
12726 case VMX_EXIT_VMREAD:
12727 case VMX_EXIT_VMRESUME:
12728 case VMX_EXIT_VMWRITE:
12729 case VMX_EXIT_VMXOFF:
12730 case VMX_EXIT_VMXON:
12731 case VMX_EXIT_MOV_CRX:
12732 case VMX_EXIT_MOV_DRX:
12733 case VMX_EXIT_IO_INSTR:
12734 case VMX_EXIT_RDMSR:
12735 case VMX_EXIT_WRMSR:
12736 case VMX_EXIT_MWAIT:
12737 case VMX_EXIT_MONITOR:
12738 case VMX_EXIT_PAUSE:
12739 case VMX_EXIT_GDTR_IDTR_ACCESS:
12740 case VMX_EXIT_LDTR_TR_ACCESS:
12741 case VMX_EXIT_INVEPT:
12742 case VMX_EXIT_RDTSCP:
12743 case VMX_EXIT_INVVPID:
12744 case VMX_EXIT_WBINVD:
12745 case VMX_EXIT_XSETBV:
12746 case VMX_EXIT_RDRAND:
12747 case VMX_EXIT_INVPCID:
12748 case VMX_EXIT_VMFUNC:
12749 case VMX_EXIT_RDSEED:
12750 case VMX_EXIT_XSAVES:
12751 case VMX_EXIT_XRSTORS:
12752 {
12753 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12754 AssertRCReturn(rc, rc);
12755 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12756 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12757 return VINF_EM_DBG_STEPPED;
12758 break;
12759 }
12760
12761 /* Errors and unexpected events: */
12762 case VMX_EXIT_INIT_SIGNAL:
12763 case VMX_EXIT_SIPI:
12764 case VMX_EXIT_IO_SMI:
12765 case VMX_EXIT_SMI:
12766 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12767 case VMX_EXIT_ERR_MSR_LOAD:
12768 case VMX_EXIT_ERR_MACHINE_CHECK:
12769 case VMX_EXIT_PML_FULL:
12770 case VMX_EXIT_VIRTUALIZED_EOI:
12771 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12772 break;
12773
12774 default:
12775 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12776 break;
12777 }
12778 }
12779
12780 /*
12781 * Check for debugger event breakpoints and dtrace probes.
12782 */
12783 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12784 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12785 {
12786 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12787 if (rcStrict != VINF_SUCCESS)
12788 return rcStrict;
12789 }
12790
12791 /*
12792 * Normal processing.
12793 */
12794#ifdef HMVMX_USE_FUNCTION_TABLE
12795 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12796#else
12797 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12798#endif
12799}
12800
12801
12802/**
12803 * Single steps guest code using hardware-assisted VMX.
12804 *
12805 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12806 * but single-stepping through the hypervisor debugger.
12807 *
12808 * @returns Strict VBox status code (i.e. informational status codes too).
12809 * @param pVCpu The cross context virtual CPU structure.
12810 * @param pcLoops Pointer to the number of executed loops.
12811 *
12812 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12813 */
12814static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12815{
12816 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12817 Assert(pcLoops);
12818 Assert(*pcLoops <= cMaxResumeLoops);
12819
12820 VMXTRANSIENT VmxTransient;
12821 RT_ZERO(VmxTransient);
12822 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12823
12824 /* Set HMCPU indicators. */
12825 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12826 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12827 pVCpu->hm.s.fDebugWantRdTscExit = false;
12828 pVCpu->hm.s.fUsingDebugLoop = true;
12829
12830 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12831 VMXRUNDBGSTATE DbgState;
12832 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12833 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12834
12835 /*
12836 * The loop.
12837 */
12838 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12839 for (;;)
12840 {
12841 Assert(!HMR0SuspendPending());
12842 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12843 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12844 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12845
12846 /* Set up VM-execution controls the next two can respond to. */
12847 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12848
12849 /*
12850 * Preparatory work for running guest code, this may force us to
12851 * return to ring-3.
12852 *
12853 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12854 */
12855 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12856 if (rcStrict != VINF_SUCCESS)
12857 break;
12858
12859 /* Interrupts are disabled at this point! */
12860 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12861
12862 /* Override any obnoxious code in the above two calls. */
12863 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12864
12865 /*
12866 * Finally execute the guest.
12867 */
12868 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12869
12870 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12871 /* Interrupts are re-enabled at this point! */
12872
12873 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12874 if (RT_SUCCESS(rcRun))
12875 { /* very likely */ }
12876 else
12877 {
12878 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12879 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12880 return rcRun;
12881 }
12882
12883 /* Profile the VM-exit. */
12884 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12885 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12886 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12887 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12888 HMVMX_START_EXIT_DISPATCH_PROF();
12889
12890 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12891
12892 /*
12893 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12894 */
12895 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12896 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12897 if (rcStrict != VINF_SUCCESS)
12898 break;
12899 if (++(*pcLoops) > cMaxResumeLoops)
12900 {
12901 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12902 rcStrict = VINF_EM_RAW_INTERRUPT;
12903 break;
12904 }
12905
12906 /*
12907 * Stepping: Did the RIP change, if so, consider it a single step.
12908 * Otherwise, make sure one of the TFs gets set.
12909 */
12910 if (fStepping)
12911 {
12912 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12913 AssertRC(rc);
12914 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12915 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12916 {
12917 rcStrict = VINF_EM_DBG_STEPPED;
12918 break;
12919 }
12920 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12921 }
12922
12923 /*
12924 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12925 */
12926 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12927 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12928 }
12929
12930 /*
12931 * Clear the X86_EFL_TF if necessary.
12932 */
12933 if (pVCpu->hm.s.fClearTrapFlag)
12934 {
12935 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12936 AssertRC(rc);
12937 pVCpu->hm.s.fClearTrapFlag = false;
12938 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12939 }
12940 /** @todo there seems to be issues with the resume flag when the monitor trap
12941 * flag is pending without being used. Seen early in bios init when
12942 * accessing APIC page in protected mode. */
12943
12944 /*
12945 * Restore VM-exit control settings as we may not re-enter this function the
12946 * next time around.
12947 */
12948 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12949
12950 /* Restore HMCPU indicators. */
12951 pVCpu->hm.s.fUsingDebugLoop = false;
12952 pVCpu->hm.s.fDebugWantRdTscExit = false;
12953 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12954
12955 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12956 return rcStrict;
12957}
12958
12959
12960/** @} */
12961
12962
12963/**
12964 * Checks if any expensive dtrace probes are enabled and we should go to the
12965 * debug loop.
12966 *
12967 * @returns true if we should use debug loop, false if not.
12968 */
12969static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12970{
12971 /* It's probably faster to OR the raw 32-bit counter variables together.
12972 Since the variables are in an array and the probes are next to one
12973 another (more or less), we have good locality. So, better read
12974 eight-nine cache lines ever time and only have one conditional, than
12975 128+ conditionals, right? */
12976 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12977 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12978 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12979 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12980 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12981 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12982 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12983 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12984 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12985 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12986 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12987 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12988 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12989 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12990 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12991 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12992 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12993 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12994 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12995 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12996 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12997 ) != 0
12998 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12999 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
13000 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
13001 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
13002 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
13003 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
13004 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
13005 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
13006 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
13007 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
13008 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
13009 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
13010 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
13011 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
13012 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
13013 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
13014 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
13015 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
13016 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
13017 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
13018 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
13019 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
13020 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
13021 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
13022 | VBOXVMM_INSTR_STR_ENABLED_RAW()
13023 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
13024 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
13025 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
13026 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
13027 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13028 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13029 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13030 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13031 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13032 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13033 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13034 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13035 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13036 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13037 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13038 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13039 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13040 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13041 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13042 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13043 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13044 ) != 0
13045 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13046 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13047 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13048 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13049 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13050 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13051 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13052 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13053 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13054 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13055 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13056 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13057 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13058 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13059 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13060 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13061 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13062 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13063 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13064 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13065 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13066 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13067 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13068 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13069 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13070 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13071 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13072 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13073 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13074 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13075 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13076 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13077 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13078 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13079 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13080 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13081 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13082 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13083 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13084 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13085 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13086 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13087 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13088 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13089 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13090 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13091 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13092 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13093 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13094 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13095 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13096 ) != 0;
13097}
13098
13099
13100/**
13101 * Runs the guest using hardware-assisted VMX.
13102 *
13103 * @returns Strict VBox status code (i.e. informational status codes too).
13104 * @param pVCpu The cross context virtual CPU structure.
13105 */
13106VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13107{
13108 AssertPtr(pVCpu);
13109 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13110 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13111 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13112 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13113
13114 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13115
13116 VBOXSTRICTRC rcStrict;
13117 uint32_t cLoops = 0;
13118 for (;;)
13119 {
13120#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13121 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13122#else
13123 bool const fInNestedGuestMode = false;
13124#endif
13125 if (!fInNestedGuestMode)
13126 {
13127 if ( !pVCpu->hm.s.fUseDebugLoop
13128 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13129 && !DBGFIsStepping(pVCpu)
13130 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13131 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13132 else
13133 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13134 }
13135#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13136 else
13137 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13138
13139 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13140 {
13141 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13142 continue;
13143 }
13144 if (rcStrict == VINF_VMX_VMEXIT)
13145 {
13146 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13147 continue;
13148 }
13149#endif
13150 break;
13151 }
13152
13153 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13154 switch (rcLoop)
13155 {
13156 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13157 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13158 }
13159
13160 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13161 if (RT_FAILURE(rc2))
13162 {
13163 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13164 rcStrict = rc2;
13165 }
13166 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13167 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13168 return rcStrict;
13169}
13170
13171
13172#ifndef HMVMX_USE_FUNCTION_TABLE
13173/**
13174 * Handles a guest VM-exit from hardware-assisted VMX execution.
13175 *
13176 * @returns Strict VBox status code (i.e. informational status codes too).
13177 * @param pVCpu The cross context virtual CPU structure.
13178 * @param pVmxTransient The VMX-transient structure.
13179 */
13180DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13181{
13182#ifdef DEBUG_ramshankar
13183#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13184 do { \
13185 if (a_fSave != 0) \
13186 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13187 VBOXSTRICTRC rcStrict = a_CallExpr; \
13188 if (a_fSave != 0) \
13189 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13190 return rcStrict; \
13191 } while (0)
13192#else
13193# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13194#endif
13195 uint32_t const uExitReason = pVmxTransient->uExitReason;
13196 switch (uExitReason)
13197 {
13198 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13199 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13200 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13201 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13202 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13203 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13204 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13205 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13206 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13207 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13208 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13209 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13210 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13211 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13212 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13213 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13214 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13215 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13216 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13217 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13218 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13219 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13220 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13221 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13222 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13223 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13224 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13225 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13226 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13227 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13228#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13229 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13230 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13231 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13232 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13233 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13234 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13235 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13236 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13237 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13238 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13239 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13240#else
13241 case VMX_EXIT_VMCLEAR:
13242 case VMX_EXIT_VMLAUNCH:
13243 case VMX_EXIT_VMPTRLD:
13244 case VMX_EXIT_VMPTRST:
13245 case VMX_EXIT_VMREAD:
13246 case VMX_EXIT_VMRESUME:
13247 case VMX_EXIT_VMWRITE:
13248 case VMX_EXIT_VMXOFF:
13249 case VMX_EXIT_VMXON:
13250 case VMX_EXIT_INVVPID:
13251 case VMX_EXIT_INVEPT:
13252 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13253#endif
13254
13255 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13256 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13257 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13258
13259 case VMX_EXIT_INIT_SIGNAL:
13260 case VMX_EXIT_SIPI:
13261 case VMX_EXIT_IO_SMI:
13262 case VMX_EXIT_SMI:
13263 case VMX_EXIT_ERR_MSR_LOAD:
13264 case VMX_EXIT_ERR_MACHINE_CHECK:
13265 case VMX_EXIT_PML_FULL:
13266 case VMX_EXIT_VIRTUALIZED_EOI:
13267 case VMX_EXIT_GDTR_IDTR_ACCESS:
13268 case VMX_EXIT_LDTR_TR_ACCESS:
13269 case VMX_EXIT_APIC_WRITE:
13270 case VMX_EXIT_RDRAND:
13271 case VMX_EXIT_RSM:
13272 case VMX_EXIT_VMFUNC:
13273 case VMX_EXIT_ENCLS:
13274 case VMX_EXIT_RDSEED:
13275 case VMX_EXIT_XSAVES:
13276 case VMX_EXIT_XRSTORS:
13277 case VMX_EXIT_UMWAIT:
13278 case VMX_EXIT_TPAUSE:
13279 default:
13280 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13281 }
13282#undef VMEXIT_CALL_RET
13283}
13284#endif /* !HMVMX_USE_FUNCTION_TABLE */
13285
13286
13287#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13288/**
13289 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13290 *
13291 * @returns Strict VBox status code (i.e. informational status codes too).
13292 * @param pVCpu The cross context virtual CPU structure.
13293 * @param pVmxTransient The VMX-transient structure.
13294 */
13295DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13296{
13297 uint32_t const uExitReason = pVmxTransient->uExitReason;
13298 switch (uExitReason)
13299 {
13300 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13301 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13302 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13303 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13304 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13305
13306 /*
13307 * We shouldn't direct host physical interrupts to the nested-guest.
13308 */
13309 case VMX_EXIT_EXT_INT:
13310 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13311
13312 /*
13313 * Instructions that cause VM-exits unconditionally or the condition is
13314 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13315 * happens, it's guaranteed to be a nested-guest VM-exit).
13316 *
13317 * - Provides VM-exit instruction length ONLY.
13318 */
13319 case VMX_EXIT_CPUID: /* Unconditional. */
13320 case VMX_EXIT_VMCALL:
13321 case VMX_EXIT_GETSEC:
13322 case VMX_EXIT_INVD:
13323 case VMX_EXIT_XSETBV:
13324 case VMX_EXIT_VMLAUNCH:
13325 case VMX_EXIT_VMRESUME:
13326 case VMX_EXIT_VMXOFF:
13327 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13328 case VMX_EXIT_VMFUNC:
13329 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13330
13331 /*
13332 * Instructions that cause VM-exits unconditionally or the condition is
13333 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13334 * happens, it's guaranteed to be a nested-guest VM-exit).
13335 *
13336 * - Provides VM-exit instruction length.
13337 * - Provides VM-exit information.
13338 * - Optionally provides Exit qualification.
13339 *
13340 * Since Exit qualification is 0 for all VM-exits where it is not
13341 * applicable, reading and passing it to the guest should produce
13342 * defined behavior.
13343 *
13344 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13345 */
13346 case VMX_EXIT_INVEPT: /* Unconditional. */
13347 case VMX_EXIT_INVVPID:
13348 case VMX_EXIT_VMCLEAR:
13349 case VMX_EXIT_VMPTRLD:
13350 case VMX_EXIT_VMPTRST:
13351 case VMX_EXIT_VMXON:
13352 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13353 case VMX_EXIT_LDTR_TR_ACCESS:
13354 case VMX_EXIT_RDRAND:
13355 case VMX_EXIT_RDSEED:
13356 case VMX_EXIT_XSAVES:
13357 case VMX_EXIT_XRSTORS:
13358 case VMX_EXIT_UMWAIT:
13359 case VMX_EXIT_TPAUSE:
13360 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13361
13362 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13363 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13364 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13365 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13366 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13367 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13368 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13369 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13370 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13371 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13372 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13373 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13374 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13375 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13376 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13377 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13378 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13379 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13380 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13381
13382 case VMX_EXIT_PREEMPT_TIMER:
13383 {
13384 /** @todo NSTVMX: Preempt timer. */
13385 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13386 }
13387
13388 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13389 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13390
13391 case VMX_EXIT_VMREAD:
13392 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13393
13394 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13395 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13396
13397 case VMX_EXIT_INIT_SIGNAL:
13398 case VMX_EXIT_SIPI:
13399 case VMX_EXIT_IO_SMI:
13400 case VMX_EXIT_SMI:
13401 case VMX_EXIT_ERR_MSR_LOAD:
13402 case VMX_EXIT_ERR_MACHINE_CHECK:
13403 case VMX_EXIT_PML_FULL:
13404 case VMX_EXIT_RSM:
13405 default:
13406 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13407 }
13408}
13409#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13410
13411
13412/** @name VM-exit helpers.
13413 * @{
13414 */
13415/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13416/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13417/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13418
13419/** Macro for VM-exits called unexpectedly. */
13420#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13421 do { \
13422 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13423 return VERR_VMX_UNEXPECTED_EXIT; \
13424 } while (0)
13425
13426#ifdef VBOX_STRICT
13427/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13428# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13429 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13430
13431# define HMVMX_ASSERT_PREEMPT_CPUID() \
13432 do { \
13433 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13434 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13435 } while (0)
13436
13437# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13438 do { \
13439 AssertPtr((a_pVCpu)); \
13440 AssertPtr((a_pVmxTransient)); \
13441 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13442 Assert((a_pVmxTransient)->pVmcsInfo); \
13443 Assert(ASMIntAreEnabled()); \
13444 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13445 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13446 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13447 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13448 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13449 HMVMX_ASSERT_PREEMPT_CPUID(); \
13450 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13451 } while (0)
13452
13453# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13454 do { \
13455 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13456 Assert((a_pVmxTransient)->fIsNestedGuest); \
13457 } while (0)
13458
13459# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13460 do { \
13461 Log4Func(("\n")); \
13462 } while (0)
13463#else
13464# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13465 do { \
13466 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13467 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13468 } while (0)
13469
13470# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13471 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13472
13473# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13474#endif
13475
13476#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13477/** Macro that does the necessary privilege checks and intercepted VM-exits for
13478 * guests that attempted to execute a VMX instruction. */
13479# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13480 do \
13481 { \
13482 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13483 if (rcStrictTmp == VINF_SUCCESS) \
13484 { /* likely */ } \
13485 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13486 { \
13487 Assert((a_pVCpu)->hm.s.Event.fPending); \
13488 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13489 return VINF_SUCCESS; \
13490 } \
13491 else \
13492 { \
13493 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13494 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13495 } \
13496 } while (0)
13497
13498/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13499# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13500 do \
13501 { \
13502 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13503 (a_pGCPtrEffAddr)); \
13504 if (rcStrictTmp == VINF_SUCCESS) \
13505 { /* likely */ } \
13506 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13507 { \
13508 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13509 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13510 NOREF(uXcptTmp); \
13511 return VINF_SUCCESS; \
13512 } \
13513 else \
13514 { \
13515 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13516 return rcStrictTmp; \
13517 } \
13518 } while (0)
13519#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13520
13521
13522/**
13523 * Advances the guest RIP by the specified number of bytes.
13524 *
13525 * @param pVCpu The cross context virtual CPU structure.
13526 * @param cbInstr Number of bytes to advance the RIP by.
13527 *
13528 * @remarks No-long-jump zone!!!
13529 */
13530DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13531{
13532 /* Advance the RIP. */
13533 pVCpu->cpum.GstCtx.rip += cbInstr;
13534 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13535
13536 /* Update interrupt inhibition. */
13537 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13538 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13539 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13540}
13541
13542
13543/**
13544 * Advances the guest RIP after reading it from the VMCS.
13545 *
13546 * @returns VBox status code, no informational status codes.
13547 * @param pVCpu The cross context virtual CPU structure.
13548 * @param pVmxTransient The VMX-transient structure.
13549 *
13550 * @remarks No-long-jump zone!!!
13551 */
13552static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13553{
13554 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13555 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13556 AssertRCReturn(rc, rc);
13557
13558 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13559 return VINF_SUCCESS;
13560}
13561
13562
13563/**
13564 * Handle a condition that occurred while delivering an event through the guest or
13565 * nested-guest IDT.
13566 *
13567 * @returns Strict VBox status code (i.e. informational status codes too).
13568 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13569 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13570 * to continue execution of the guest which will delivery the \#DF.
13571 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13572 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13573 *
13574 * @param pVCpu The cross context virtual CPU structure.
13575 * @param pVmxTransient The VMX-transient structure.
13576 *
13577 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13578 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13579 * is due to an EPT violation, PML full or SPP-related event.
13580 *
13581 * @remarks No-long-jump zone!!!
13582 */
13583static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13584{
13585 Assert(!pVCpu->hm.s.Event.fPending);
13586 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13587 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13588 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13589 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13590 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13591
13592 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13593 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13594 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13595 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13596 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13597 {
13598 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13599 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13600
13601 /*
13602 * If the event was a software interrupt (generated with INT n) or a software exception
13603 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13604 * can handle the VM-exit and continue guest execution which will re-execute the
13605 * instruction rather than re-injecting the exception, as that can cause premature
13606 * trips to ring-3 before injection and involve TRPM which currently has no way of
13607 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13608 * the problem).
13609 */
13610 IEMXCPTRAISE enmRaise;
13611 IEMXCPTRAISEINFO fRaiseInfo;
13612 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13613 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13614 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13615 {
13616 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13617 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13618 }
13619 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13620 {
13621 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13622 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13623 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13624
13625 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13626 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13627
13628 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13629
13630 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13631 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13632 {
13633 pVmxTransient->fVectoringPF = true;
13634 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13635 }
13636 }
13637 else
13638 {
13639 /*
13640 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13641 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13642 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13643 */
13644 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13645 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13646 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13647 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13648 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13649 }
13650
13651 /*
13652 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13653 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13654 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13655 * subsequent VM-entry would fail, see @bugref{7445}.
13656 *
13657 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13658 */
13659 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13660 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13661 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13662 && CPUMIsGuestNmiBlocking(pVCpu))
13663 {
13664 CPUMSetGuestNmiBlocking(pVCpu, false);
13665 }
13666
13667 switch (enmRaise)
13668 {
13669 case IEMXCPTRAISE_CURRENT_XCPT:
13670 {
13671 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13672 Assert(rcStrict == VINF_SUCCESS);
13673 break;
13674 }
13675
13676 case IEMXCPTRAISE_PREV_EVENT:
13677 {
13678 uint32_t u32ErrCode;
13679 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13680 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13681 else
13682 u32ErrCode = 0;
13683
13684 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13685 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13686 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13687 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13688
13689 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13690 pVCpu->hm.s.Event.u32ErrCode));
13691 Assert(rcStrict == VINF_SUCCESS);
13692 break;
13693 }
13694
13695 case IEMXCPTRAISE_REEXEC_INSTR:
13696 Assert(rcStrict == VINF_SUCCESS);
13697 break;
13698
13699 case IEMXCPTRAISE_DOUBLE_FAULT:
13700 {
13701 /*
13702 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13703 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13704 */
13705 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13706 {
13707 pVmxTransient->fVectoringDoublePF = true;
13708 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13709 pVCpu->cpum.GstCtx.cr2));
13710 rcStrict = VINF_SUCCESS;
13711 }
13712 else
13713 {
13714 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13715 hmR0VmxSetPendingXcptDF(pVCpu);
13716 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13717 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13718 rcStrict = VINF_HM_DOUBLE_FAULT;
13719 }
13720 break;
13721 }
13722
13723 case IEMXCPTRAISE_TRIPLE_FAULT:
13724 {
13725 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13726 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13727 rcStrict = VINF_EM_RESET;
13728 break;
13729 }
13730
13731 case IEMXCPTRAISE_CPU_HANG:
13732 {
13733 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13734 rcStrict = VERR_EM_GUEST_CPU_HANG;
13735 break;
13736 }
13737
13738 default:
13739 {
13740 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13741 rcStrict = VERR_VMX_IPE_2;
13742 break;
13743 }
13744 }
13745 }
13746 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13747 && !CPUMIsGuestNmiBlocking(pVCpu))
13748 {
13749 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13750 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13751 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13752 {
13753 /*
13754 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13755 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13756 * that NMIs remain blocked until the IRET execution is completed.
13757 *
13758 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13759 */
13760 CPUMSetGuestNmiBlocking(pVCpu, true);
13761 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13762 }
13763 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13764 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13765 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13766 {
13767 /*
13768 * Execution of IRET caused an EPT violation, page-modification log-full event or
13769 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13770 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13771 * that NMIs remain blocked until the IRET execution is completed.
13772 *
13773 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13774 */
13775 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13776 {
13777 CPUMSetGuestNmiBlocking(pVCpu, true);
13778 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13779 }
13780 }
13781 }
13782
13783 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13784 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13785 return rcStrict;
13786}
13787
13788
13789#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13790/**
13791 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13792 * guest attempting to execute a VMX instruction.
13793 *
13794 * @returns Strict VBox status code (i.e. informational status codes too).
13795 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13796 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13797 *
13798 * @param pVCpu The cross context virtual CPU structure.
13799 * @param uExitReason The VM-exit reason.
13800 *
13801 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13802 * @remarks No-long-jump zone!!!
13803 */
13804static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13805{
13806 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13807 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13808
13809 /*
13810 * The physical CPU would have already checked the CPU mode/code segment.
13811 * We shall just assert here for paranoia.
13812 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13813 */
13814 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13815 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13816 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13817
13818 if (uExitReason == VMX_EXIT_VMXON)
13819 {
13820 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13821
13822 /*
13823 * We check CR4.VMXE because it is required to be always set while in VMX operation
13824 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13825 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13826 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13827 */
13828 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13829 {
13830 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13831 hmR0VmxSetPendingXcptUD(pVCpu);
13832 return VINF_HM_PENDING_XCPT;
13833 }
13834 }
13835 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13836 {
13837 /*
13838 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13839 * (other than VMXON), we need to raise a #UD.
13840 */
13841 Log4Func(("Not in VMX root mode -> #UD\n"));
13842 hmR0VmxSetPendingXcptUD(pVCpu);
13843 return VINF_HM_PENDING_XCPT;
13844 }
13845
13846 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13847 return VINF_SUCCESS;
13848}
13849
13850/**
13851 * Decodes the memory operand of an instruction that caused a VM-exit.
13852 *
13853 * The Exit qualification field provides the displacement field for memory
13854 * operand instructions, if any.
13855 *
13856 * @returns Strict VBox status code (i.e. informational status codes too).
13857 * @retval VINF_SUCCESS if the operand was successfully decoded.
13858 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13859 * operand.
13860 * @param pVCpu The cross context virtual CPU structure.
13861 * @param uExitInstrInfo The VM-exit instruction information field.
13862 * @param enmMemAccess The memory operand's access type (read or write).
13863 * @param GCPtrDisp The instruction displacement field, if any. For
13864 * RIP-relative addressing pass RIP + displacement here.
13865 * @param pGCPtrMem Where to store the effective destination memory address.
13866 *
13867 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13868 * virtual-8086 mode hence skips those checks while verifying if the
13869 * segment is valid.
13870 */
13871static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13872 PRTGCPTR pGCPtrMem)
13873{
13874 Assert(pGCPtrMem);
13875 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13876 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13877 | CPUMCTX_EXTRN_CR0);
13878
13879 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13880 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13881 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13882
13883 VMXEXITINSTRINFO ExitInstrInfo;
13884 ExitInstrInfo.u = uExitInstrInfo;
13885 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13886 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13887 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13888 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13889 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13890 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13891 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13892 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13893 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13894
13895 /*
13896 * Validate instruction information.
13897 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13898 */
13899 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13900 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13901 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13902 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13903 AssertLogRelMsgReturn(fIsMemOperand,
13904 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13905
13906 /*
13907 * Compute the complete effective address.
13908 *
13909 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13910 * See AMD spec. 4.5.2 "Segment Registers".
13911 */
13912 RTGCPTR GCPtrMem = GCPtrDisp;
13913 if (fBaseRegValid)
13914 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13915 if (fIdxRegValid)
13916 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13917
13918 RTGCPTR const GCPtrOff = GCPtrMem;
13919 if ( !fIsLongMode
13920 || iSegReg >= X86_SREG_FS)
13921 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13922 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13923
13924 /*
13925 * Validate effective address.
13926 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13927 */
13928 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13929 Assert(cbAccess > 0);
13930 if (fIsLongMode)
13931 {
13932 if (X86_IS_CANONICAL(GCPtrMem))
13933 {
13934 *pGCPtrMem = GCPtrMem;
13935 return VINF_SUCCESS;
13936 }
13937
13938 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13939 * "Data Limit Checks in 64-bit Mode". */
13940 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13941 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13942 return VINF_HM_PENDING_XCPT;
13943 }
13944
13945 /*
13946 * This is a watered down version of iemMemApplySegment().
13947 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13948 * and segment CPL/DPL checks are skipped.
13949 */
13950 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13951 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13952 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13953
13954 /* Check if the segment is present and usable. */
13955 if ( pSel->Attr.n.u1Present
13956 && !pSel->Attr.n.u1Unusable)
13957 {
13958 Assert(pSel->Attr.n.u1DescType);
13959 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13960 {
13961 /* Check permissions for the data segment. */
13962 if ( enmMemAccess == VMXMEMACCESS_WRITE
13963 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13964 {
13965 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13966 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13967 return VINF_HM_PENDING_XCPT;
13968 }
13969
13970 /* Check limits if it's a normal data segment. */
13971 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13972 {
13973 if ( GCPtrFirst32 > pSel->u32Limit
13974 || GCPtrLast32 > pSel->u32Limit)
13975 {
13976 Log4Func(("Data segment limit exceeded. "
13977 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13978 GCPtrLast32, pSel->u32Limit));
13979 if (iSegReg == X86_SREG_SS)
13980 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13981 else
13982 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13983 return VINF_HM_PENDING_XCPT;
13984 }
13985 }
13986 else
13987 {
13988 /* Check limits if it's an expand-down data segment.
13989 Note! The upper boundary is defined by the B bit, not the G bit! */
13990 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13991 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13992 {
13993 Log4Func(("Expand-down data segment limit exceeded. "
13994 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13995 GCPtrLast32, pSel->u32Limit));
13996 if (iSegReg == X86_SREG_SS)
13997 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13998 else
13999 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14000 return VINF_HM_PENDING_XCPT;
14001 }
14002 }
14003 }
14004 else
14005 {
14006 /* Check permissions for the code segment. */
14007 if ( enmMemAccess == VMXMEMACCESS_WRITE
14008 || ( enmMemAccess == VMXMEMACCESS_READ
14009 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
14010 {
14011 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
14012 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
14013 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14014 return VINF_HM_PENDING_XCPT;
14015 }
14016
14017 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
14018 if ( GCPtrFirst32 > pSel->u32Limit
14019 || GCPtrLast32 > pSel->u32Limit)
14020 {
14021 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
14022 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
14023 if (iSegReg == X86_SREG_SS)
14024 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14025 else
14026 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14027 return VINF_HM_PENDING_XCPT;
14028 }
14029 }
14030 }
14031 else
14032 {
14033 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14034 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14035 return VINF_HM_PENDING_XCPT;
14036 }
14037
14038 *pGCPtrMem = GCPtrMem;
14039 return VINF_SUCCESS;
14040}
14041#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
14042
14043
14044/**
14045 * VM-exit helper for LMSW.
14046 */
14047static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
14048{
14049 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14050 AssertRCReturn(rc, rc);
14051
14052 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14053 AssertMsg( rcStrict == VINF_SUCCESS
14054 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14055
14056 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14057 if (rcStrict == VINF_IEM_RAISED_XCPT)
14058 {
14059 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14060 rcStrict = VINF_SUCCESS;
14061 }
14062
14063 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14064 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14065 return rcStrict;
14066}
14067
14068
14069/**
14070 * VM-exit helper for CLTS.
14071 */
14072static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14073{
14074 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14075 AssertRCReturn(rc, rc);
14076
14077 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14078 AssertMsg( rcStrict == VINF_SUCCESS
14079 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14080
14081 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14082 if (rcStrict == VINF_IEM_RAISED_XCPT)
14083 {
14084 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14085 rcStrict = VINF_SUCCESS;
14086 }
14087
14088 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14089 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14090 return rcStrict;
14091}
14092
14093
14094/**
14095 * VM-exit helper for MOV from CRx (CRx read).
14096 */
14097static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14098{
14099 Assert(iCrReg < 16);
14100 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14101
14102 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14103 AssertRCReturn(rc, rc);
14104
14105 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14106 AssertMsg( rcStrict == VINF_SUCCESS
14107 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14108
14109 if (iGReg == X86_GREG_xSP)
14110 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14111 else
14112 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14113#ifdef VBOX_WITH_STATISTICS
14114 switch (iCrReg)
14115 {
14116 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14117 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14118 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14119 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14120 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14121 }
14122#endif
14123 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14124 return rcStrict;
14125}
14126
14127
14128/**
14129 * VM-exit helper for MOV to CRx (CRx write).
14130 */
14131static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14132{
14133 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14134 AssertRCReturn(rc, rc);
14135
14136 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14137 AssertMsg( rcStrict == VINF_SUCCESS
14138 || rcStrict == VINF_IEM_RAISED_XCPT
14139 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14140
14141 switch (iCrReg)
14142 {
14143 case 0:
14144 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14145 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14146 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14147 break;
14148
14149 case 2:
14150 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14151 /* Nothing to do here, CR2 it's not part of the VMCS. */
14152 break;
14153
14154 case 3:
14155 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14156 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14157 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14158 break;
14159
14160 case 4:
14161 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14162 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14163 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14164 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14165 break;
14166
14167 case 8:
14168 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14169 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14170 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14171 break;
14172
14173 default:
14174 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14175 break;
14176 }
14177
14178 if (rcStrict == VINF_IEM_RAISED_XCPT)
14179 {
14180 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14181 rcStrict = VINF_SUCCESS;
14182 }
14183 return rcStrict;
14184}
14185
14186
14187/**
14188 * VM-exit exception handler for \#PF (Page-fault exception).
14189 *
14190 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14191 */
14192static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14193{
14194 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14195 PVM pVM = pVCpu->CTX_SUFF(pVM);
14196 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14197 AssertRCReturn(rc, rc);
14198
14199 if (!pVM->hm.s.fNestedPaging)
14200 { /* likely */ }
14201 else
14202 {
14203#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14204 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14205#endif
14206 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14207 if (!pVmxTransient->fVectoringDoublePF)
14208 {
14209 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14210 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14211 }
14212 else
14213 {
14214 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14215 Assert(!pVmxTransient->fIsNestedGuest);
14216 hmR0VmxSetPendingXcptDF(pVCpu);
14217 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14218 }
14219 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14220 return rc;
14221 }
14222
14223 Assert(!pVmxTransient->fIsNestedGuest);
14224
14225 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14226 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14227 if (pVmxTransient->fVectoringPF)
14228 {
14229 Assert(pVCpu->hm.s.Event.fPending);
14230 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14231 }
14232
14233 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14234 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14235 AssertRCReturn(rc, rc);
14236
14237 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14238 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14239
14240 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14241 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14242
14243 Log4Func(("#PF: rc=%Rrc\n", rc));
14244 if (rc == VINF_SUCCESS)
14245 {
14246 /*
14247 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14248 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14249 */
14250 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14251 TRPMResetTrap(pVCpu);
14252 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14253 return rc;
14254 }
14255
14256 if (rc == VINF_EM_RAW_GUEST_TRAP)
14257 {
14258 if (!pVmxTransient->fVectoringDoublePF)
14259 {
14260 /* It's a guest page fault and needs to be reflected to the guest. */
14261 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14262 TRPMResetTrap(pVCpu);
14263 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14264 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14265 uGstErrorCode, pVmxTransient->uExitQual);
14266 }
14267 else
14268 {
14269 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14270 TRPMResetTrap(pVCpu);
14271 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14272 hmR0VmxSetPendingXcptDF(pVCpu);
14273 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14274 }
14275
14276 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14277 return VINF_SUCCESS;
14278 }
14279
14280 TRPMResetTrap(pVCpu);
14281 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14282 return rc;
14283}
14284
14285
14286/**
14287 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14288 *
14289 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14290 */
14291static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14292{
14293 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14294 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14295
14296 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14297 AssertRCReturn(rc, rc);
14298
14299 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14300 {
14301 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14302 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14303
14304 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14305 * provides VM-exit instruction length. If this causes problem later,
14306 * disassemble the instruction like it's done on AMD-V. */
14307 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14308 AssertRCReturn(rc2, rc2);
14309 return rc;
14310 }
14311
14312 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14313 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14314 return VINF_SUCCESS;
14315}
14316
14317
14318/**
14319 * VM-exit exception handler for \#BP (Breakpoint exception).
14320 *
14321 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14322 */
14323static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14324{
14325 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14326 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14327
14328 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14329 AssertRCReturn(rc, rc);
14330
14331 if (!pVmxTransient->fIsNestedGuest)
14332 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14333 else
14334 rc = VINF_EM_RAW_GUEST_TRAP;
14335 if (rc == VINF_EM_RAW_GUEST_TRAP)
14336 {
14337 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14338 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14339 }
14340
14341 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14342 return rc;
14343}
14344
14345
14346/**
14347 * VM-exit exception handler for \#AC (Alignment-check exception).
14348 *
14349 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14350 */
14351static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14352{
14353 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14354 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14355
14356 /* Re-inject it. We'll detect any nesting before getting here. */
14357 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14358 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14359 return VINF_SUCCESS;
14360}
14361
14362
14363/**
14364 * VM-exit exception handler for \#DB (Debug exception).
14365 *
14366 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14367 */
14368static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14369{
14370 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14371 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14372
14373 /*
14374 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14375 */
14376 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14377 AssertRCReturn(rc, rc);
14378
14379 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14380 uint64_t const uDR6 = X86_DR6_INIT_VAL
14381 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14382 | X86_DR6_BD | X86_DR6_BS));
14383
14384 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14385 if (!pVmxTransient->fIsNestedGuest)
14386 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14387 else
14388 rc = VINF_EM_RAW_GUEST_TRAP;
14389 Log6Func(("rc=%Rrc\n", rc));
14390 if (rc == VINF_EM_RAW_GUEST_TRAP)
14391 {
14392 /*
14393 * The exception was for the guest. Update DR6, DR7.GD and
14394 * IA32_DEBUGCTL.LBR before forwarding it.
14395 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14396 */
14397 VMMRZCallRing3Disable(pVCpu);
14398 HM_DISABLE_PREEMPT(pVCpu);
14399
14400 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14401 pCtx->dr[6] |= uDR6;
14402 if (CPUMIsGuestDebugStateActive(pVCpu))
14403 ASMSetDR6(pCtx->dr[6]);
14404
14405 HM_RESTORE_PREEMPT();
14406 VMMRZCallRing3Enable(pVCpu);
14407
14408 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14409 AssertRCReturn(rc, rc);
14410
14411 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14412 pCtx->dr[7] &= ~X86_DR7_GD;
14413
14414 /* Paranoia. */
14415 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14416 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14417
14418 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14419 AssertRCReturn(rc, rc);
14420
14421 /*
14422 * Raise #DB in the guest.
14423 *
14424 * It is important to reflect exactly what the VM-exit gave us (preserving the
14425 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14426 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14427 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14428 *
14429 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14430 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14431 */
14432 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14433 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14434 return VINF_SUCCESS;
14435 }
14436
14437 /*
14438 * Not a guest trap, must be a hypervisor related debug event then.
14439 * Update DR6 in case someone is interested in it.
14440 */
14441 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14442 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14443 CPUMSetHyperDR6(pVCpu, uDR6);
14444
14445 return rc;
14446}
14447
14448
14449/**
14450 * Hacks its way around the lovely mesa driver's backdoor accesses.
14451 *
14452 * @sa hmR0SvmHandleMesaDrvGp.
14453 */
14454static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14455{
14456 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14457 RT_NOREF(pCtx);
14458
14459 /* For now we'll just skip the instruction. */
14460 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14461}
14462
14463
14464/**
14465 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14466 * backdoor logging w/o checking what it is running inside.
14467 *
14468 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14469 * backdoor port and magic numbers loaded in registers.
14470 *
14471 * @returns true if it is, false if it isn't.
14472 * @sa hmR0SvmIsMesaDrvGp.
14473 */
14474DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14475{
14476 /* 0xed: IN eAX,dx */
14477 uint8_t abInstr[1];
14478 if (pVmxTransient->cbInstr != sizeof(abInstr))
14479 return false;
14480
14481 /* Check that it is #GP(0). */
14482 if (pVmxTransient->uExitIntErrorCode != 0)
14483 return false;
14484
14485 /* Check magic and port. */
14486 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14487 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14488 if (pCtx->rax != UINT32_C(0x564d5868))
14489 return false;
14490 if (pCtx->dx != UINT32_C(0x5658))
14491 return false;
14492
14493 /* Flat ring-3 CS. */
14494 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14495 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14496 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14497 if (pCtx->cs.Attr.n.u2Dpl != 3)
14498 return false;
14499 if (pCtx->cs.u64Base != 0)
14500 return false;
14501
14502 /* Check opcode. */
14503 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14504 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14505 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14506 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14507 if (RT_FAILURE(rc))
14508 return false;
14509 if (abInstr[0] != 0xed)
14510 return false;
14511
14512 return true;
14513}
14514
14515
14516/**
14517 * VM-exit exception handler for \#GP (General-protection exception).
14518 *
14519 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14520 */
14521static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14522{
14523 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14524 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14525
14526 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14527 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14528 if (pVmcsInfo->RealMode.fRealOnV86Active)
14529 { /* likely */ }
14530 else
14531 {
14532#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14533 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14534#endif
14535 /*
14536 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14537 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14538 */
14539 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14540 AssertRCReturn(rc, rc);
14541 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14542 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14543
14544 if ( pVmxTransient->fIsNestedGuest
14545 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14546 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14547 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14548 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14549 else
14550 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14551 return rc;
14552 }
14553
14554 Assert(CPUMIsGuestInRealModeEx(pCtx));
14555 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14556 Assert(!pVmxTransient->fIsNestedGuest);
14557
14558 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14559 AssertRCReturn(rc, rc);
14560
14561 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14562 if (rcStrict == VINF_SUCCESS)
14563 {
14564 if (!CPUMIsGuestInRealModeEx(pCtx))
14565 {
14566 /*
14567 * The guest is no longer in real-mode, check if we can continue executing the
14568 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14569 */
14570 pVmcsInfo->RealMode.fRealOnV86Active = false;
14571 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14572 {
14573 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14574 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14575 }
14576 else
14577 {
14578 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14579 rcStrict = VINF_EM_RESCHEDULE;
14580 }
14581 }
14582 else
14583 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14584 }
14585 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14586 {
14587 rcStrict = VINF_SUCCESS;
14588 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14589 }
14590 return VBOXSTRICTRC_VAL(rcStrict);
14591}
14592
14593
14594/**
14595 * VM-exit exception handler wrapper for all other exceptions that are not handled
14596 * by a specific handler.
14597 *
14598 * This simply re-injects the exception back into the VM without any special
14599 * processing.
14600 *
14601 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14602 */
14603static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14604{
14605 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14606
14607#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14608 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14609 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14610 ("uVector=%#x u32XcptBitmap=%#X32\n",
14611 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14612 NOREF(pVmcsInfo);
14613#endif
14614
14615 /*
14616 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14617 * would have been handled while checking exits due to event delivery.
14618 */
14619 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14620
14621#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14622 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14623 AssertRCReturn(rc, rc);
14624 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14625#endif
14626
14627#ifdef VBOX_WITH_STATISTICS
14628 switch (uVector)
14629 {
14630 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14631 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14632 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14633 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14634 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14635 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14636 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14637 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14638 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14639 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14640 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14641 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14642 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14643 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14644 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14645 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14646 default:
14647 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14648 break;
14649 }
14650#endif
14651
14652 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14653 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14654 NOREF(uVector);
14655
14656 /* Re-inject the original exception into the guest. */
14657 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14658 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14659 return VINF_SUCCESS;
14660}
14661
14662
14663/**
14664 * VM-exit exception handler for all exceptions (except NMIs!).
14665 *
14666 * @remarks This may be called for both guests and nested-guests. Take care to not
14667 * make assumptions and avoid doing anything that is not relevant when
14668 * executing a nested-guest (e.g., Mesa driver hacks).
14669 */
14670static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14671{
14672 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
14673
14674 /*
14675 * If this VM-exit occurred while delivering an event through the guest IDT, take
14676 * action based on the return code and additional hints (e.g. for page-faults)
14677 * that will be updated in the VMX transient structure.
14678 */
14679 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14680 if (rcStrict == VINF_SUCCESS)
14681 {
14682 /*
14683 * If an exception caused a VM-exit due to delivery of an event, the original
14684 * event may have to be re-injected into the guest. We shall reinject it and
14685 * continue guest execution. However, page-fault is a complicated case and
14686 * needs additional processing done in hmR0VmxExitXcptPF().
14687 */
14688 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14689 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14690 if ( !pVCpu->hm.s.Event.fPending
14691 || uVector == X86_XCPT_PF)
14692 {
14693 switch (uVector)
14694 {
14695 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14696 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14697 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14698 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14699 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14700 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14701 default:
14702 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14703 }
14704 }
14705 /* else: inject pending event before resuming guest execution. */
14706 }
14707 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14708 {
14709 Assert(pVCpu->hm.s.Event.fPending);
14710 rcStrict = VINF_SUCCESS;
14711 }
14712
14713 return rcStrict;
14714}
14715/** @} */
14716
14717
14718/** @name VM-exit handlers.
14719 * @{
14720 */
14721/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14722/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14723/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14724
14725/**
14726 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14727 */
14728HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14729{
14730 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14731 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14732 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14733 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14734 return VINF_SUCCESS;
14735 return VINF_EM_RAW_INTERRUPT;
14736}
14737
14738
14739/**
14740 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14741 * VM-exit.
14742 */
14743HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14744{
14745 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14746 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14747
14748 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14749 AssertRCReturn(rc, rc);
14750
14751 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14752 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14753 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14754
14755 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14756 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14757 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14758 NOREF(pVmcsInfo);
14759
14760 VBOXSTRICTRC rcStrict;
14761 switch (uExitIntType)
14762 {
14763 /*
14764 * Host physical NMIs:
14765 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14766 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14767 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14768 *
14769 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14770 * See Intel spec. 27.5.5 "Updating Non-Register State".
14771 */
14772 case VMX_EXIT_INT_INFO_TYPE_NMI:
14773 {
14774 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14775 break;
14776 }
14777
14778 /*
14779 * Privileged software exceptions (#DB from ICEBP),
14780 * Software exceptions (#BP and #OF),
14781 * Hardware exceptions:
14782 * Process the required exceptions and resume guest execution if possible.
14783 */
14784 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14785 Assert(uVector == X86_XCPT_DB);
14786 RT_FALL_THRU();
14787 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14788 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14789 RT_FALL_THRU();
14790 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14791 {
14792 NOREF(uVector);
14793 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14794 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14795 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14796 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14797 AssertRCReturn(rc, rc);
14798
14799 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14800 break;
14801 }
14802
14803 default:
14804 {
14805 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14806 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14807 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14808 break;
14809 }
14810 }
14811
14812 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14813 return rcStrict;
14814}
14815
14816
14817/**
14818 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14819 */
14820HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14821{
14822 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14823
14824 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14825 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14826 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14827 AssertRCReturn(rc, rc);
14828
14829 /* Evaluate and deliver pending events and resume guest execution. */
14830 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14831 return VINF_SUCCESS;
14832}
14833
14834
14835/**
14836 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14837 */
14838HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14839{
14840 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14841
14842 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14843 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14844 {
14845 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14846 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14847 }
14848
14849 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14850
14851 /*
14852 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14853 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14854 */
14855 uint32_t fIntrState;
14856 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14857 AssertRCReturn(rc, rc);
14858 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14859 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14860 {
14861 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14862 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14863
14864 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14865 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14866 AssertRCReturn(rc, rc);
14867 }
14868
14869 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14870 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14871 AssertRCReturn(rc, rc);
14872
14873 /* Evaluate and deliver pending events and resume guest execution. */
14874 return VINF_SUCCESS;
14875}
14876
14877
14878/**
14879 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14880 */
14881HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14882{
14883 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14884 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14885}
14886
14887
14888/**
14889 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14890 */
14891HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14892{
14893 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14894 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14895}
14896
14897
14898/**
14899 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14900 */
14901HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14902{
14903 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14904
14905 /*
14906 * Get the state we need and update the exit history entry.
14907 */
14908 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14909 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14910 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14911 AssertRCReturn(rc, rc);
14912
14913 VBOXSTRICTRC rcStrict;
14914 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14915 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14916 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14917 if (!pExitRec)
14918 {
14919 /*
14920 * Regular CPUID instruction execution.
14921 */
14922 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14923 if (rcStrict == VINF_SUCCESS)
14924 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14925 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14926 {
14927 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14928 rcStrict = VINF_SUCCESS;
14929 }
14930 }
14931 else
14932 {
14933 /*
14934 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14935 */
14936 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14937 AssertRCReturn(rc2, rc2);
14938
14939 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14940 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14941
14942 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14943 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14944
14945 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14946 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14947 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14948 }
14949 return rcStrict;
14950}
14951
14952
14953/**
14954 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14955 */
14956HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14957{
14958 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14959
14960 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14961 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14962 AssertRCReturn(rc, rc);
14963
14964 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14965 return VINF_EM_RAW_EMULATE_INSTR;
14966
14967 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14968 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14969}
14970
14971
14972/**
14973 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14974 */
14975HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14976{
14977 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14978
14979 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14980 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14981 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14982 AssertRCReturn(rc, rc);
14983
14984 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
14985 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14986 {
14987 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14988 we must reset offsetting on VM-entry. See @bugref{6634}. */
14989 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14990 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14991 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14992 }
14993 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14994 {
14995 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14996 rcStrict = VINF_SUCCESS;
14997 }
14998 return rcStrict;
14999}
15000
15001
15002/**
15003 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
15004 */
15005HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15006{
15007 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15008
15009 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15010 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
15011 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15012 AssertRCReturn(rc, rc);
15013
15014 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
15015 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15016 {
15017 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15018 we must reset offsetting on VM-reentry. See @bugref{6634}. */
15019 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15020 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15021 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15022 }
15023 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15024 {
15025 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15026 rcStrict = VINF_SUCCESS;
15027 }
15028 return rcStrict;
15029}
15030
15031
15032/**
15033 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
15034 */
15035HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15036{
15037 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15038
15039 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15040 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
15041 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
15042 AssertRCReturn(rc, rc);
15043
15044 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15045 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
15046 if (RT_LIKELY(rc == VINF_SUCCESS))
15047 {
15048 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15049 Assert(pVmxTransient->cbInstr == 2);
15050 }
15051 else
15052 {
15053 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
15054 rc = VERR_EM_INTERPRETER;
15055 }
15056 return rc;
15057}
15058
15059
15060/**
15061 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
15062 */
15063HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15064{
15065 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15066
15067 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
15068 if (EMAreHypercallInstructionsEnabled(pVCpu))
15069 {
15070 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15071 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
15072 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
15073 AssertRCReturn(rc, rc);
15074
15075 /* Perform the hypercall. */
15076 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
15077 if (rcStrict == VINF_SUCCESS)
15078 {
15079 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15080 AssertRCReturn(rc, rc);
15081 }
15082 else
15083 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15084 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15085 || RT_FAILURE(rcStrict));
15086
15087 /* If the hypercall changes anything other than guest's general-purpose registers,
15088 we would need to reload the guest changed bits here before VM-entry. */
15089 }
15090 else
15091 Log4Func(("Hypercalls not enabled\n"));
15092
15093 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15094 if (RT_FAILURE(rcStrict))
15095 {
15096 hmR0VmxSetPendingXcptUD(pVCpu);
15097 rcStrict = VINF_SUCCESS;
15098 }
15099
15100 return rcStrict;
15101}
15102
15103
15104/**
15105 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15106 */
15107HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15108{
15109 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15110 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15111
15112 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15113 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15114 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15115 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15116 AssertRCReturn(rc, rc);
15117
15118 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15119
15120 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15121 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15122 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15123 {
15124 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15125 rcStrict = VINF_SUCCESS;
15126 }
15127 else
15128 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15129 VBOXSTRICTRC_VAL(rcStrict)));
15130 return rcStrict;
15131}
15132
15133
15134/**
15135 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15136 */
15137HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15138{
15139 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15140
15141 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15142 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15143 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15144 AssertRCReturn(rc, rc);
15145
15146 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15147 if (rcStrict == VINF_SUCCESS)
15148 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15149 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15150 {
15151 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15152 rcStrict = VINF_SUCCESS;
15153 }
15154
15155 return rcStrict;
15156}
15157
15158
15159/**
15160 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15161 */
15162HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15163{
15164 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15165
15166 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15167 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15168 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15169 AssertRCReturn(rc, rc);
15170
15171 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15172 if (RT_SUCCESS(rcStrict))
15173 {
15174 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15175 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15176 rcStrict = VINF_SUCCESS;
15177 }
15178
15179 return rcStrict;
15180}
15181
15182
15183/**
15184 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15185 * VM-exit.
15186 */
15187HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15188{
15189 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15190 return VINF_EM_RESET;
15191}
15192
15193
15194/**
15195 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15196 */
15197HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15198{
15199 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15200
15201 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15202 AssertRCReturn(rc, rc);
15203
15204 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15205 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15206 rc = VINF_SUCCESS;
15207 else
15208 rc = VINF_EM_HALT;
15209
15210 if (rc != VINF_SUCCESS)
15211 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15212 return rc;
15213}
15214
15215
15216/**
15217 * VM-exit handler for instructions that result in a \#UD exception delivered to
15218 * the guest.
15219 */
15220HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15221{
15222 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15223 hmR0VmxSetPendingXcptUD(pVCpu);
15224 return VINF_SUCCESS;
15225}
15226
15227
15228/**
15229 * VM-exit handler for expiry of the VMX-preemption timer.
15230 */
15231HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15232{
15233 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15234
15235 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15236 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15237
15238 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15239 PVM pVM = pVCpu->CTX_SUFF(pVM);
15240 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15241 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15242 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15243}
15244
15245
15246/**
15247 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15248 */
15249HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15250{
15251 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15252
15253 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15254 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15255 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15256 AssertRCReturn(rc, rc);
15257
15258 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15259 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15260 : HM_CHANGED_RAISED_XCPT_MASK);
15261
15262 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15263 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15264
15265 return rcStrict;
15266}
15267
15268
15269/**
15270 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15271 */
15272HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15273{
15274 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15275 /** @todo Use VM-exit instruction information. */
15276 return VERR_EM_INTERPRETER;
15277}
15278
15279
15280/**
15281 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15282 * VM-exit.
15283 */
15284HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15285{
15286 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15287 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15288 AssertRCReturn(rc, rc);
15289
15290 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15291 if (RT_FAILURE(rc))
15292 return rc;
15293
15294 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15295 NOREF(uInvalidReason);
15296
15297#ifdef VBOX_STRICT
15298 uint32_t fIntrState;
15299 RTHCUINTREG uHCReg;
15300 uint64_t u64Val;
15301 uint32_t u32Val;
15302 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15303 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15304 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15305 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15306 AssertRCReturn(rc, rc);
15307
15308 Log4(("uInvalidReason %u\n", uInvalidReason));
15309 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15310 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15311 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15312 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15313
15314 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15315 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15316 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15317 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15318 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15319 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15320 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15321 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15322 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15323 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15324 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15325 {
15326 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15327 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15328 }
15329
15330 hmR0DumpRegs(pVCpu);
15331#endif
15332
15333 return VERR_VMX_INVALID_GUEST_STATE;
15334}
15335
15336/**
15337 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15338 */
15339HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15340{
15341 /*
15342 * Cummulative notes of all recognized but unexpected VM-exits.
15343 *
15344 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15345 * nested-paging is used.
15346 *
15347 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15348 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15349 * this function (and thereby stop VM execution) for handling such instructions.
15350 *
15351 *
15352 * VMX_EXIT_INIT_SIGNAL:
15353 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15354 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15355 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15356 *
15357 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15358 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15359 * See Intel spec. "23.8 Restrictions on VMX operation".
15360 *
15361 * VMX_EXIT_SIPI:
15362 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15363 * activity state is used. We don't make use of it as our guests don't have direct
15364 * access to the host local APIC.
15365 *
15366 * See Intel spec. 25.3 "Other Causes of VM-exits".
15367 *
15368 * VMX_EXIT_IO_SMI:
15369 * VMX_EXIT_SMI:
15370 * This can only happen if we support dual-monitor treatment of SMI, which can be
15371 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15372 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15373 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15374 *
15375 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15376 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15377 *
15378 * VMX_EXIT_ERR_MSR_LOAD:
15379 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15380 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15381 * execution.
15382 *
15383 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15384 *
15385 * VMX_EXIT_ERR_MACHINE_CHECK:
15386 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15387 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15388 * #MC exception abort class exception is raised. We thus cannot assume a
15389 * reasonable chance of continuing any sort of execution and we bail.
15390 *
15391 * See Intel spec. 15.1 "Machine-check Architecture".
15392 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15393 *
15394 * VMX_EXIT_PML_FULL:
15395 * VMX_EXIT_VIRTUALIZED_EOI:
15396 * VMX_EXIT_APIC_WRITE:
15397 * We do not currently support any of these features and thus they are all unexpected
15398 * VM-exits.
15399 *
15400 * VMX_EXIT_GDTR_IDTR_ACCESS:
15401 * VMX_EXIT_LDTR_TR_ACCESS:
15402 * VMX_EXIT_RDRAND:
15403 * VMX_EXIT_RSM:
15404 * VMX_EXIT_VMFUNC:
15405 * VMX_EXIT_ENCLS:
15406 * VMX_EXIT_RDSEED:
15407 * VMX_EXIT_XSAVES:
15408 * VMX_EXIT_XRSTORS:
15409 * VMX_EXIT_UMWAIT:
15410 * VMX_EXIT_TPAUSE:
15411 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15412 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15413 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15414 *
15415 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15416 */
15417 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15418 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15419 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15420}
15421
15422
15423/**
15424 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15425 */
15426HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15427{
15428 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15429
15430 /** @todo Optimize this: We currently drag in in the whole MSR state
15431 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15432 * MSRs required. That would require changes to IEM and possibly CPUM too.
15433 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15434 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15435 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15436 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15437 switch (idMsr)
15438 {
15439 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15440 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15441 }
15442
15443 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15444 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15445 AssertRCReturn(rc, rc);
15446
15447 Log4Func(("ecx=%#RX32\n", idMsr));
15448
15449#ifdef VBOX_STRICT
15450 Assert(!pVmxTransient->fIsNestedGuest);
15451 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15452 {
15453 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15454 && idMsr != MSR_K6_EFER)
15455 {
15456 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15457 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15458 }
15459 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15460 {
15461 Assert(pVmcsInfo->pvMsrBitmap);
15462 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15463 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15464 {
15465 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15466 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15467 }
15468 }
15469 }
15470#endif
15471
15472 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15473 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15474 if (rcStrict == VINF_SUCCESS)
15475 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15476 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15477 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15478 {
15479 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15480 rcStrict = VINF_SUCCESS;
15481 }
15482 else
15483 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15484
15485 return rcStrict;
15486}
15487
15488
15489/**
15490 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15491 */
15492HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15493{
15494 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15495
15496 /** @todo Optimize this: We currently drag in in the whole MSR state
15497 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15498 * MSRs required. That would require changes to IEM and possibly CPUM too.
15499 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15500 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15501 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15502
15503 /*
15504 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15505 * Although we don't need to fetch the base as it will be overwritten shortly, while
15506 * loading guest-state we would also load the entire segment register including limit
15507 * and attributes and thus we need to load them here.
15508 */
15509 switch (idMsr)
15510 {
15511 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15512 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15513 }
15514
15515 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15516 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15517 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15518 AssertRCReturn(rc, rc);
15519
15520 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15521
15522 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15523 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15524
15525 if (rcStrict == VINF_SUCCESS)
15526 {
15527 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15528
15529 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15530 if ( idMsr == MSR_IA32_APICBASE
15531 || ( idMsr >= MSR_IA32_X2APIC_START
15532 && idMsr <= MSR_IA32_X2APIC_END))
15533 {
15534 /*
15535 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15536 * When full APIC register virtualization is implemented we'll have to make
15537 * sure APIC state is saved from the VMCS before IEM changes it.
15538 */
15539 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15540 }
15541 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15542 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15543 else if (idMsr == MSR_K6_EFER)
15544 {
15545 /*
15546 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15547 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15548 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15549 */
15550 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15551 }
15552
15553 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15554 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15555 {
15556 switch (idMsr)
15557 {
15558 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15559 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15560 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15561 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15562 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15563 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15564 default:
15565 {
15566 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15567 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15568 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15569 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15570 break;
15571 }
15572 }
15573 }
15574#ifdef VBOX_STRICT
15575 else
15576 {
15577 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15578 switch (idMsr)
15579 {
15580 case MSR_IA32_SYSENTER_CS:
15581 case MSR_IA32_SYSENTER_EIP:
15582 case MSR_IA32_SYSENTER_ESP:
15583 case MSR_K8_FS_BASE:
15584 case MSR_K8_GS_BASE:
15585 {
15586 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15587 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15588 }
15589
15590 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15591 default:
15592 {
15593 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15594 {
15595 /* EFER MSR writes are always intercepted. */
15596 if (idMsr != MSR_K6_EFER)
15597 {
15598 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15599 idMsr));
15600 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15601 }
15602 }
15603
15604 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15605 {
15606 Assert(pVmcsInfo->pvMsrBitmap);
15607 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15608 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15609 {
15610 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15611 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15612 }
15613 }
15614 break;
15615 }
15616 }
15617 }
15618#endif /* VBOX_STRICT */
15619 }
15620 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15621 {
15622 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15623 rcStrict = VINF_SUCCESS;
15624 }
15625 else
15626 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15627
15628 return rcStrict;
15629}
15630
15631
15632/**
15633 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15634 */
15635HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15636{
15637 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15638
15639 /** @todo The guest has likely hit a contended spinlock. We might want to
15640 * poke a schedule different guest VCPU. */
15641 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15642 if (RT_SUCCESS(rc))
15643 return VINF_EM_RAW_INTERRUPT;
15644
15645 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15646 return rc;
15647}
15648
15649
15650/**
15651 * VM-exit handler for when the TPR value is lowered below the specified
15652 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15653 */
15654HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15655{
15656 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15657 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15658
15659 /*
15660 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15661 * We'll re-evaluate pending interrupts and inject them before the next VM
15662 * entry so we can just continue execution here.
15663 */
15664 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15665 return VINF_SUCCESS;
15666}
15667
15668
15669/**
15670 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15671 * VM-exit.
15672 *
15673 * @retval VINF_SUCCESS when guest execution can continue.
15674 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15675 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15676 * incompatible guest state for VMX execution (real-on-v86 case).
15677 */
15678HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15679{
15680 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15681 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15682
15683 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15684 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15685 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15686 AssertRCReturn(rc, rc);
15687
15688 VBOXSTRICTRC rcStrict;
15689 PVM pVM = pVCpu->CTX_SUFF(pVM);
15690 uint64_t const uExitQual = pVmxTransient->uExitQual;
15691 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15692 switch (uAccessType)
15693 {
15694 /*
15695 * MOV to CRx.
15696 */
15697 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15698 {
15699 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15700 AssertRCReturn(rc, rc);
15701
15702 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15703 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15704 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15705 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15706
15707 /*
15708 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15709 * - When nested paging isn't used.
15710 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15711 * - We are executing in the VM debug loop.
15712 */
15713 Assert( iCrReg != 3
15714 || !pVM->hm.s.fNestedPaging
15715 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15716 || pVCpu->hm.s.fUsingDebugLoop);
15717
15718 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15719 Assert( iCrReg != 8
15720 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15721
15722 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15723 AssertMsg( rcStrict == VINF_SUCCESS
15724 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15725
15726 /*
15727 * This is a kludge for handling switches back to real mode when we try to use
15728 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15729 * deal with special selector values, so we have to return to ring-3 and run
15730 * there till the selector values are V86 mode compatible.
15731 *
15732 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15733 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15734 * this function.
15735 */
15736 if ( iCrReg == 0
15737 && rcStrict == VINF_SUCCESS
15738 && !pVM->hm.s.vmx.fUnrestrictedGuest
15739 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15740 && (uOldCr0 & X86_CR0_PE)
15741 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15742 {
15743 /** @todo Check selectors rather than returning all the time. */
15744 Assert(!pVmxTransient->fIsNestedGuest);
15745 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15746 rcStrict = VINF_EM_RESCHEDULE_REM;
15747 }
15748 break;
15749 }
15750
15751 /*
15752 * MOV from CRx.
15753 */
15754 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15755 {
15756 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15757 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15758
15759 /*
15760 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15761 * - When nested paging isn't used.
15762 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15763 * - We are executing in the VM debug loop.
15764 */
15765 Assert( iCrReg != 3
15766 || !pVM->hm.s.fNestedPaging
15767 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15768 || pVCpu->hm.s.fUsingDebugLoop);
15769
15770 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15771 Assert( iCrReg != 8
15772 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15773
15774 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15775 break;
15776 }
15777
15778 /*
15779 * CLTS (Clear Task-Switch Flag in CR0).
15780 */
15781 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15782 {
15783 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15784 break;
15785 }
15786
15787 /*
15788 * LMSW (Load Machine-Status Word into CR0).
15789 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15790 */
15791 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15792 {
15793 RTGCPTR GCPtrEffDst;
15794 uint8_t const cbInstr = pVmxTransient->cbInstr;
15795 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15796 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15797 if (fMemOperand)
15798 {
15799 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15800 AssertRCReturn(rc, rc);
15801 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15802 }
15803 else
15804 GCPtrEffDst = NIL_RTGCPTR;
15805 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15806 break;
15807 }
15808
15809 default:
15810 {
15811 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15812 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15813 }
15814 }
15815
15816 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15817 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15818 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15819
15820 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15821 NOREF(pVM);
15822 return rcStrict;
15823}
15824
15825
15826/**
15827 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15828 * VM-exit.
15829 */
15830HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15831{
15832 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15833 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15834
15835 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15836 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15837 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15838 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15839 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15840 | CPUMCTX_EXTRN_EFER);
15841 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15842 AssertRCReturn(rc, rc);
15843
15844 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15845 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15846 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15847 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15848 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15849 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15850 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15851 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15852
15853 /*
15854 * Update exit history to see if this exit can be optimized.
15855 */
15856 VBOXSTRICTRC rcStrict;
15857 PCEMEXITREC pExitRec = NULL;
15858 if ( !fGstStepping
15859 && !fDbgStepping)
15860 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15861 !fIOString
15862 ? !fIOWrite
15863 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15864 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15865 : !fIOWrite
15866 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15867 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15868 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15869 if (!pExitRec)
15870 {
15871 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15872 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15873
15874 uint32_t const cbValue = s_aIOSizes[uIOSize];
15875 uint32_t const cbInstr = pVmxTransient->cbInstr;
15876 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15877 PVM pVM = pVCpu->CTX_SUFF(pVM);
15878 if (fIOString)
15879 {
15880 /*
15881 * INS/OUTS - I/O String instruction.
15882 *
15883 * Use instruction-information if available, otherwise fall back on
15884 * interpreting the instruction.
15885 */
15886 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15887 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15888 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15889 if (fInsOutsInfo)
15890 {
15891 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15892 AssertRCReturn(rc2, rc2);
15893 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15894 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15895 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15896 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15897 if (fIOWrite)
15898 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15899 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15900 else
15901 {
15902 /*
15903 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15904 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15905 * See Intel Instruction spec. for "INS".
15906 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15907 */
15908 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15909 }
15910 }
15911 else
15912 rcStrict = IEMExecOne(pVCpu);
15913
15914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15915 fUpdateRipAlready = true;
15916 }
15917 else
15918 {
15919 /*
15920 * IN/OUT - I/O instruction.
15921 */
15922 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15923 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15924 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15925 if (fIOWrite)
15926 {
15927 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15928 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15929 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15930 && !pCtx->eflags.Bits.u1TF)
15931 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15932 }
15933 else
15934 {
15935 uint32_t u32Result = 0;
15936 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15937 if (IOM_SUCCESS(rcStrict))
15938 {
15939 /* Save result of I/O IN instr. in AL/AX/EAX. */
15940 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15941 }
15942 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15943 && !pCtx->eflags.Bits.u1TF)
15944 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15945 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15946 }
15947 }
15948
15949 if (IOM_SUCCESS(rcStrict))
15950 {
15951 if (!fUpdateRipAlready)
15952 {
15953 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15955 }
15956
15957 /*
15958 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15959 * while booting Fedora 17 64-bit guest.
15960 *
15961 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15962 */
15963 if (fIOString)
15964 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15965
15966 /*
15967 * If any I/O breakpoints are armed, we need to check if one triggered
15968 * and take appropriate action.
15969 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15970 */
15971 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15972 AssertRCReturn(rc, rc);
15973
15974 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15975 * execution engines about whether hyper BPs and such are pending. */
15976 uint32_t const uDr7 = pCtx->dr[7];
15977 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15978 && X86_DR7_ANY_RW_IO(uDr7)
15979 && (pCtx->cr4 & X86_CR4_DE))
15980 || DBGFBpIsHwIoArmed(pVM)))
15981 {
15982 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15983
15984 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15985 VMMRZCallRing3Disable(pVCpu);
15986 HM_DISABLE_PREEMPT(pVCpu);
15987
15988 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15989
15990 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15991 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15992 {
15993 /* Raise #DB. */
15994 if (fIsGuestDbgActive)
15995 ASMSetDR6(pCtx->dr[6]);
15996 if (pCtx->dr[7] != uDr7)
15997 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15998
15999 hmR0VmxSetPendingXcptDB(pVCpu);
16000 }
16001 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
16002 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
16003 else if ( rcStrict2 != VINF_SUCCESS
16004 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
16005 rcStrict = rcStrict2;
16006 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
16007
16008 HM_RESTORE_PREEMPT();
16009 VMMRZCallRing3Enable(pVCpu);
16010 }
16011 }
16012
16013#ifdef VBOX_STRICT
16014 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16015 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
16016 Assert(!fIOWrite);
16017 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16018 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
16019 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
16020 Assert(fIOWrite);
16021 else
16022 {
16023# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
16024 * statuses, that the VMM device and some others may return. See
16025 * IOM_SUCCESS() for guidance. */
16026 AssertMsg( RT_FAILURE(rcStrict)
16027 || rcStrict == VINF_SUCCESS
16028 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
16029 || rcStrict == VINF_EM_DBG_BREAKPOINT
16030 || rcStrict == VINF_EM_RAW_GUEST_TRAP
16031 || rcStrict == VINF_EM_RAW_TO_R3
16032 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16033# endif
16034 }
16035#endif
16036 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
16037 }
16038 else
16039 {
16040 /*
16041 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
16042 */
16043 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16044 AssertRCReturn(rc2, rc2);
16045 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
16046 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
16047 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
16048 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16049 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
16050 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
16051
16052 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16053 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16054
16055 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16056 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16057 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16058 }
16059 return rcStrict;
16060}
16061
16062
16063/**
16064 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16065 * VM-exit.
16066 */
16067HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16068{
16069 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16070
16071 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16072 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16073 AssertRCReturn(rc, rc);
16074 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16075 {
16076 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16077 AssertRCReturn(rc, rc);
16078 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16079 {
16080 uint32_t uErrCode;
16081 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16082 {
16083 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16084 AssertRCReturn(rc, rc);
16085 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16086 }
16087 else
16088 uErrCode = 0;
16089
16090 RTGCUINTPTR GCPtrFaultAddress;
16091 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16092 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16093 else
16094 GCPtrFaultAddress = 0;
16095
16096 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16097 AssertRCReturn(rc, rc);
16098
16099 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16100 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16101
16102 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16103 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16104 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16105 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16106 }
16107 }
16108
16109 /* Fall back to the interpreter to emulate the task-switch. */
16110 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16111 return VERR_EM_INTERPRETER;
16112}
16113
16114
16115/**
16116 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16117 */
16118HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16119{
16120 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16121
16122 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16123 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16124 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16125 AssertRCReturn(rc, rc);
16126 return VINF_EM_DBG_STEPPED;
16127}
16128
16129
16130/**
16131 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16132 */
16133HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16134{
16135 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16136 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16137
16138 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16139 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16140 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16141 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16142 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16143 AssertRCReturn(rc, rc);
16144
16145 /*
16146 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16147 */
16148 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16149 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16150 {
16151 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16152 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16153 {
16154 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16155 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16156 }
16157 }
16158 else
16159 {
16160 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16161 return rcStrict;
16162 }
16163
16164 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16165 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16166 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16167 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16168 AssertRCReturn(rc, rc);
16169
16170 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16171 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16172 switch (uAccessType)
16173 {
16174 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16175 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16176 {
16177 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16178 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16179 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16180
16181 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16182 GCPhys &= PAGE_BASE_GC_MASK;
16183 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16184 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16185 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16186
16187 PVM pVM = pVCpu->CTX_SUFF(pVM);
16188 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16189 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
16190 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16191 CPUMCTX2CORE(pCtx), GCPhys);
16192 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16193 if ( rcStrict == VINF_SUCCESS
16194 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16195 || rcStrict == VERR_PAGE_NOT_PRESENT)
16196 {
16197 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16198 | HM_CHANGED_GUEST_APIC_TPR);
16199 rcStrict = VINF_SUCCESS;
16200 }
16201 break;
16202 }
16203
16204 default:
16205 {
16206 Log4Func(("uAccessType=%#x\n", uAccessType));
16207 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16208 break;
16209 }
16210 }
16211
16212 if (rcStrict != VINF_SUCCESS)
16213 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16214 return rcStrict;
16215}
16216
16217
16218/**
16219 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16220 * VM-exit.
16221 */
16222HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16223{
16224 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16225
16226 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16227 if (pVmxTransient->fWasGuestDebugStateActive)
16228 {
16229 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16230 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16231 }
16232
16233 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16234 if ( !pVCpu->hm.s.fSingleInstruction
16235 && !pVmxTransient->fWasHyperDebugStateActive)
16236 {
16237 Assert(!DBGFIsStepping(pVCpu));
16238 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16239
16240 /* Don't intercept MOV DRx any more. */
16241 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16242 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16243 AssertRCReturn(rc, rc);
16244
16245 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16246 VMMRZCallRing3Disable(pVCpu);
16247 HM_DISABLE_PREEMPT(pVCpu);
16248
16249 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16250 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16251 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16252
16253 HM_RESTORE_PREEMPT();
16254 VMMRZCallRing3Enable(pVCpu);
16255
16256#ifdef VBOX_WITH_STATISTICS
16257 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16258 AssertRCReturn(rc, rc);
16259 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16260 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16261 else
16262 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16263#endif
16264 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16265 return VINF_SUCCESS;
16266 }
16267
16268 /*
16269 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16270 * The EFER MSR is always up-to-date.
16271 * Update the segment registers and DR7 from the CPU.
16272 */
16273 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16274 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16275 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16276 AssertRCReturn(rc, rc);
16277 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16278
16279 PVM pVM = pVCpu->CTX_SUFF(pVM);
16280 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16281 {
16282 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16283 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16284 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16285 if (RT_SUCCESS(rc))
16286 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16287 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16288 }
16289 else
16290 {
16291 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16292 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16293 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16294 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16295 }
16296
16297 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16298 if (RT_SUCCESS(rc))
16299 {
16300 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16301 AssertRCReturn(rc2, rc2);
16302 return VINF_SUCCESS;
16303 }
16304 return rc;
16305}
16306
16307
16308/**
16309 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16310 * Conditional VM-exit.
16311 */
16312HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16313{
16314 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16315 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16316
16317 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16318 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16319 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16320 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16321 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16322 AssertRCReturn(rc, rc);
16323
16324 /*
16325 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16326 */
16327 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16328 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16329 {
16330 /*
16331 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16332 * instruction emulation to inject the original event. Otherwise, injecting the original event
16333 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16334 */
16335 if (!pVCpu->hm.s.Event.fPending)
16336 { /* likely */ }
16337 else
16338 {
16339 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16340#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16341 /** @todo NSTVMX: Think about how this should be handled. */
16342 if (pVmxTransient->fIsNestedGuest)
16343 return VERR_VMX_IPE_3;
16344#endif
16345 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16346 }
16347 }
16348 else
16349 {
16350 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16351 return rcStrict;
16352 }
16353
16354 /*
16355 * Get sufficent state and update the exit history entry.
16356 */
16357 RTGCPHYS GCPhys;
16358 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16359 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16360 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16361 AssertRCReturn(rc, rc);
16362
16363 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16364 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16365 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16366 if (!pExitRec)
16367 {
16368 /*
16369 * If we succeed, resume guest execution.
16370 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16371 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16372 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16373 * weird case. See @bugref{6043}.
16374 */
16375 PVM pVM = pVCpu->CTX_SUFF(pVM);
16376 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16377 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16378 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16379 if ( rcStrict == VINF_SUCCESS
16380 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16381 || rcStrict == VERR_PAGE_NOT_PRESENT)
16382 {
16383 /* Successfully handled MMIO operation. */
16384 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16385 | HM_CHANGED_GUEST_APIC_TPR);
16386 rcStrict = VINF_SUCCESS;
16387 }
16388 }
16389 else
16390 {
16391 /*
16392 * Frequent exit or something needing probing. Call EMHistoryExec.
16393 */
16394 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16395 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16396
16397 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16398 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16399
16400 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16401 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16402 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16403 }
16404 return rcStrict;
16405}
16406
16407
16408/**
16409 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16410 * VM-exit.
16411 */
16412HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16413{
16414 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16415 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16416
16417 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16418 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16419 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16420 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16421 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16422 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16423 AssertRCReturn(rc, rc);
16424
16425 /*
16426 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16427 */
16428 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16429 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16430 {
16431 /*
16432 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16433 * we shall resolve the nested #PF and re-inject the original event.
16434 */
16435 if (pVCpu->hm.s.Event.fPending)
16436 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16437 }
16438 else
16439 {
16440 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16441 return rcStrict;
16442 }
16443
16444 RTGCPHYS GCPhys;
16445 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16446 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16447 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16448 AssertRCReturn(rc, rc);
16449
16450 uint64_t const uExitQual = pVmxTransient->uExitQual;
16451 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16452
16453 RTGCUINT uErrorCode = 0;
16454 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16455 uErrorCode |= X86_TRAP_PF_ID;
16456 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16457 uErrorCode |= X86_TRAP_PF_RW;
16458 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16459 uErrorCode |= X86_TRAP_PF_P;
16460
16461 PVM pVM = pVCpu->CTX_SUFF(pVM);
16462 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16463 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16464
16465 /*
16466 * Handle the pagefault trap for the nested shadow table.
16467 */
16468 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16469 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16470 TRPMResetTrap(pVCpu);
16471
16472 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16473 if ( rcStrict == VINF_SUCCESS
16474 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16475 || rcStrict == VERR_PAGE_NOT_PRESENT)
16476 {
16477 /* Successfully synced our nested page tables. */
16478 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16479 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16480 return VINF_SUCCESS;
16481 }
16482
16483 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16484 return rcStrict;
16485}
16486
16487
16488#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16489/**
16490 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16491 */
16492HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16493{
16494 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16495
16496 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16497 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16498 | CPUMCTX_EXTRN_HWVIRT
16499 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16500 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16501 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16502 AssertRCReturn(rc, rc);
16503
16504 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16505
16506 VMXVEXITINFO ExitInfo;
16507 RT_ZERO(ExitInfo);
16508 ExitInfo.uReason = pVmxTransient->uExitReason;
16509 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16510 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16511 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16512 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16513
16514 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16515 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16516 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16517 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16518 {
16519 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16520 rcStrict = VINF_SUCCESS;
16521 }
16522 return rcStrict;
16523}
16524
16525
16526/**
16527 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16528 */
16529HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16530{
16531 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16532
16533 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16534 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16535 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16536 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16537 AssertRCReturn(rc, rc);
16538
16539 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16540
16541 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16542 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16543 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16544 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16545 {
16546 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16547 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16548 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16549 }
16550 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16551 return rcStrict;
16552}
16553
16554
16555/**
16556 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16557 */
16558HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16559{
16560 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16561
16562 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16563 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16564 | CPUMCTX_EXTRN_HWVIRT
16565 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16566 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16567 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16568 AssertRCReturn(rc, rc);
16569
16570 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16571
16572 VMXVEXITINFO ExitInfo;
16573 RT_ZERO(ExitInfo);
16574 ExitInfo.uReason = pVmxTransient->uExitReason;
16575 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16576 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16577 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16578 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16579
16580 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16581 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16582 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16583 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16584 {
16585 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16586 rcStrict = VINF_SUCCESS;
16587 }
16588 return rcStrict;
16589}
16590
16591
16592/**
16593 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16594 */
16595HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16596{
16597 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16598
16599 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16600 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16601 | CPUMCTX_EXTRN_HWVIRT
16602 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16603 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16604 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16605 AssertRCReturn(rc, rc);
16606
16607 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16608
16609 VMXVEXITINFO ExitInfo;
16610 RT_ZERO(ExitInfo);
16611 ExitInfo.uReason = pVmxTransient->uExitReason;
16612 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16613 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16614 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16615 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16616
16617 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16618 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16619 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16620 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16621 {
16622 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16623 rcStrict = VINF_SUCCESS;
16624 }
16625 return rcStrict;
16626}
16627
16628
16629/**
16630 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16631 */
16632HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16633{
16634 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16635
16636 /*
16637 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16638 * thus might not need to import the shadow VMCS state, it's safer just in case
16639 * code elsewhere dares look at unsynced VMCS fields.
16640 */
16641 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16642 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16643 | CPUMCTX_EXTRN_HWVIRT
16644 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16645 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16646 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16647 AssertRCReturn(rc, rc);
16648
16649 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16650
16651 VMXVEXITINFO ExitInfo;
16652 RT_ZERO(ExitInfo);
16653 ExitInfo.uReason = pVmxTransient->uExitReason;
16654 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16655 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16656 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16657 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16658 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16659
16660 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16661 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16662 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16663 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16664 {
16665 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16666 rcStrict = VINF_SUCCESS;
16667 }
16668 return rcStrict;
16669}
16670
16671
16672/**
16673 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16674 */
16675HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16676{
16677 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16678
16679 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16680 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16681 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16682 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16683 AssertRCReturn(rc, rc);
16684
16685 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16686
16687 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16688 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16689 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16690 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16691 {
16692 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16693 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16694 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16695 }
16696 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16697 return rcStrict;
16698}
16699
16700
16701/**
16702 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16703 */
16704HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16705{
16706 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16707
16708 /*
16709 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16710 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16711 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16712 */
16713 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16714 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16715 | CPUMCTX_EXTRN_HWVIRT
16716 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16717 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16718 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16719 AssertRCReturn(rc, rc);
16720
16721 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16722
16723 VMXVEXITINFO ExitInfo;
16724 RT_ZERO(ExitInfo);
16725 ExitInfo.uReason = pVmxTransient->uExitReason;
16726 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16727 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16728 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16729 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16730 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16731
16732 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16733 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16734 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16735 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16736 {
16737 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16738 rcStrict = VINF_SUCCESS;
16739 }
16740 return rcStrict;
16741}
16742
16743
16744/**
16745 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16746 */
16747HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16748{
16749 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16750
16751 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16752 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16753 | CPUMCTX_EXTRN_HWVIRT
16754 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16755 AssertRCReturn(rc, rc);
16756
16757 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16758
16759 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16760 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16761 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16762 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16763 {
16764 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16765 rcStrict = VINF_SUCCESS;
16766 }
16767 return rcStrict;
16768}
16769
16770
16771/**
16772 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16773 */
16774HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16775{
16776 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16777
16778 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16779 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16780 | CPUMCTX_EXTRN_HWVIRT
16781 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16782 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16783 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16784 AssertRCReturn(rc, rc);
16785
16786 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16787
16788 VMXVEXITINFO ExitInfo;
16789 RT_ZERO(ExitInfo);
16790 ExitInfo.uReason = pVmxTransient->uExitReason;
16791 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16792 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16793 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16794 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16795
16796 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16797 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16798 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16799 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16800 {
16801 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16802 rcStrict = VINF_SUCCESS;
16803 }
16804 return rcStrict;
16805}
16806
16807
16808/**
16809 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16810 */
16811HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16812{
16813 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16814
16815 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16816 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16817 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16818 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16819 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16820 AssertRCReturn(rc, rc);
16821
16822 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16823
16824 VMXVEXITINFO ExitInfo;
16825 RT_ZERO(ExitInfo);
16826 ExitInfo.uReason = pVmxTransient->uExitReason;
16827 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16828 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16829 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16830 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16831
16832 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16833 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16834 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16835 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16836 {
16837 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16838 rcStrict = VINF_SUCCESS;
16839 }
16840 return rcStrict;
16841}
16842#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16843/** @} */
16844
16845
16846#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16847/** @name Nested-guest VM-exit handlers.
16848 * @{
16849 */
16850/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16851/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16852/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16853
16854/**
16855 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16856 * Conditional VM-exit.
16857 */
16858HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16859{
16860 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16861
16862 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16863 AssertRCReturn(rc, rc);
16864
16865 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16866 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16867 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16868
16869 switch (uExitIntType)
16870 {
16871 /*
16872 * Physical NMIs:
16873 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16874 */
16875 case VMX_EXIT_INT_INFO_TYPE_NMI:
16876 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16877
16878 /*
16879 * Hardware exceptions,
16880 * Software exceptions,
16881 * Privileged software exceptions:
16882 * Figure out if the exception must be delivered to the guest or the nested-guest.
16883 */
16884 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16885 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16886 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16887 {
16888 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16889 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16890 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16891 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16892 AssertRCReturn(rc, rc);
16893
16894 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16895 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16896 pVmxTransient->uExitIntErrorCode);
16897 if (fIntercept)
16898 {
16899 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16900 AssertRCReturn(rc, rc);
16901
16902 /*
16903 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16904 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16905 * length. However, if delivery of a software interrupt, software exception or privileged
16906 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16907 */
16908 VMXVEXITINFO ExitInfo;
16909 RT_ZERO(ExitInfo);
16910 ExitInfo.uReason = pVmxTransient->uExitReason;
16911 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16912 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16913
16914 VMXVEXITEVENTINFO ExitEventInfo;
16915 RT_ZERO(ExitEventInfo);
16916 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16917 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16918 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16919 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16920
16921#ifdef DEBUG_ramshankar
16922 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
16923 Log4Func(("cs:rip=%#04x:%#RX64 %s err_code=%#x exit_qual=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
16924 VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo) ? "#PF" : "Unk",
16925 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16926 Log4Func(("idt_info=%#RX64 (%s) idt_errcode=%#RX32\n", pVmxTransient->uIdtVectoringInfo,
16927 VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo) ? "Valid" : "Invalid",
16928 pVmxTransient->uIdtVectoringErrorCode));
16929#endif
16930 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16931 }
16932
16933 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16934 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16935 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16936 }
16937
16938 /*
16939 * Software interrupts:
16940 * VM-exits cannot be caused by software interrupts.
16941 *
16942 * External interrupts:
16943 * This should only happen when "acknowledge external interrupts on VM-exit"
16944 * control is set. However, we never set this when executing a guest or
16945 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16946 * the guest.
16947 */
16948 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16949 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16950 default:
16951 {
16952 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16953 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16954 }
16955 }
16956}
16957
16958
16959/**
16960 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16961 * Unconditional VM-exit.
16962 */
16963HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16964{
16965 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16966 return IEMExecVmxVmexitTripleFault(pVCpu);
16967}
16968
16969
16970/**
16971 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16972 */
16973HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16974{
16975 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16976
16977 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16978 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16979 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16980}
16981
16982
16983/**
16984 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16985 */
16986HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16987{
16988 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16989
16990 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16991 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16992 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16993}
16994
16995
16996/**
16997 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16998 * Unconditional VM-exit.
16999 */
17000HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17001{
17002 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17003
17004 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17005 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17006 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17007 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17008 AssertRCReturn(rc, rc);
17009
17010 VMXVEXITINFO ExitInfo;
17011 RT_ZERO(ExitInfo);
17012 ExitInfo.uReason = pVmxTransient->uExitReason;
17013 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17014 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17015
17016 VMXVEXITEVENTINFO ExitEventInfo;
17017 RT_ZERO(ExitEventInfo);
17018 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17019 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17020 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
17021}
17022
17023
17024/**
17025 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
17026 */
17027HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17028{
17029 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17030
17031 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
17032 {
17033 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17034 AssertRCReturn(rc, rc);
17035 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17036 }
17037 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
17038}
17039
17040
17041/**
17042 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
17043 */
17044HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17045{
17046 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17047
17048 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17049 {
17050 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17051 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17052 AssertRCReturn(rc, rc);
17053
17054 VMXVEXITINFO ExitInfo;
17055 RT_ZERO(ExitInfo);
17056 ExitInfo.uReason = pVmxTransient->uExitReason;
17057 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17058 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17059 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17060 }
17061 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17062}
17063
17064
17065/**
17066 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17067 */
17068HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17069{
17070 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17071
17072 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17073 {
17074 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17075 AssertRCReturn(rc, rc);
17076 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17077 }
17078 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17079}
17080
17081
17082/**
17083 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17084 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17085 */
17086HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17087{
17088 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17089
17090 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17091 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17092
17093 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17094 AssertRCReturn(rc, rc);
17095
17096 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17097 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17098 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17099
17100 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17101 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17102 u64VmcsField &= UINT64_C(0xffffffff);
17103
17104 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17105 {
17106 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17107 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17108 AssertRCReturn(rc, rc);
17109
17110 VMXVEXITINFO ExitInfo;
17111 RT_ZERO(ExitInfo);
17112 ExitInfo.uReason = pVmxTransient->uExitReason;
17113 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17114 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17115 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17116 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17117 }
17118
17119 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17120 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17121 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17122}
17123
17124
17125/**
17126 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17127 */
17128HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17129{
17130 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17131
17132 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17133 {
17134 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17135 AssertRCReturn(rc, rc);
17136 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17137 }
17138
17139 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17140}
17141
17142
17143/**
17144 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17145 * Conditional VM-exit.
17146 */
17147HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17148{
17149 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17150
17151 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17152 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17153 AssertRCReturn(rc, rc);
17154
17155 VBOXSTRICTRC rcStrict;
17156 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17157 switch (uAccessType)
17158 {
17159 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17160 {
17161 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17162 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17163 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17164 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17165
17166 bool fIntercept;
17167 switch (iCrReg)
17168 {
17169 case 0:
17170 case 4:
17171 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17172 break;
17173
17174 case 3:
17175 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17176 break;
17177
17178 case 8:
17179 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17180 break;
17181
17182 default:
17183 fIntercept = false;
17184 break;
17185 }
17186 if (fIntercept)
17187 {
17188 VMXVEXITINFO ExitInfo;
17189 RT_ZERO(ExitInfo);
17190 ExitInfo.uReason = pVmxTransient->uExitReason;
17191 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17192 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17193 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17194 }
17195 else
17196 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17197 break;
17198 }
17199
17200 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17201 {
17202 /*
17203 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17204 * CR2 reads do not cause a VM-exit.
17205 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17206 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17207 */
17208 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17209 if ( iCrReg == 3
17210 || iCrReg == 8)
17211 {
17212 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17213 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17214 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17215 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17216 {
17217 VMXVEXITINFO ExitInfo;
17218 RT_ZERO(ExitInfo);
17219 ExitInfo.uReason = pVmxTransient->uExitReason;
17220 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17221 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17222 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17223 }
17224 else
17225 {
17226 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17227 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17228 }
17229 }
17230 else
17231 {
17232 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17233 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17234 }
17235 break;
17236 }
17237
17238 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17239 {
17240 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17241 Assert(pVmcsNstGst);
17242 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17243 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17244 if ( (uGstHostMask & X86_CR0_TS)
17245 && (uReadShadow & X86_CR0_TS))
17246 {
17247 VMXVEXITINFO ExitInfo;
17248 RT_ZERO(ExitInfo);
17249 ExitInfo.uReason = pVmxTransient->uExitReason;
17250 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17251 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17252 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17253 }
17254 else
17255 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17256 break;
17257 }
17258
17259 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17260 {
17261 RTGCPTR GCPtrEffDst;
17262 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17263 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17264 if (fMemOperand)
17265 {
17266 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17267 AssertRCReturn(rc, rc);
17268 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17269 }
17270 else
17271 GCPtrEffDst = NIL_RTGCPTR;
17272
17273 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17274 {
17275 VMXVEXITINFO ExitInfo;
17276 RT_ZERO(ExitInfo);
17277 ExitInfo.uReason = pVmxTransient->uExitReason;
17278 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17279 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17280 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17281 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17282 }
17283 else
17284 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17285 break;
17286 }
17287
17288 default:
17289 {
17290 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17291 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17292 }
17293 }
17294
17295 if (rcStrict == VINF_IEM_RAISED_XCPT)
17296 {
17297 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17298 rcStrict = VINF_SUCCESS;
17299 }
17300 return rcStrict;
17301}
17302
17303
17304/**
17305 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17306 * Conditional VM-exit.
17307 */
17308HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17309{
17310 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17311
17312 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17313 {
17314 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17315 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17316 AssertRCReturn(rc, rc);
17317
17318 VMXVEXITINFO ExitInfo;
17319 RT_ZERO(ExitInfo);
17320 ExitInfo.uReason = pVmxTransient->uExitReason;
17321 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17322 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17323 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17324 }
17325 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17326}
17327
17328
17329/**
17330 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17331 * Conditional VM-exit.
17332 */
17333HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17334{
17335 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17336
17337 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17338 AssertRCReturn(rc, rc);
17339
17340 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17341 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17342 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17343
17344 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17345 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17346 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17347 {
17348 /*
17349 * IN/OUT instruction:
17350 * - Provides VM-exit instruction length.
17351 *
17352 * INS/OUTS instruction:
17353 * - Provides VM-exit instruction length.
17354 * - Provides Guest-linear address.
17355 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17356 */
17357 PVM pVM = pVCpu->CTX_SUFF(pVM);
17358 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17359 AssertRCReturn(rc, rc);
17360
17361 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17362 pVmxTransient->ExitInstrInfo.u = 0;
17363 pVmxTransient->uGuestLinearAddr = 0;
17364
17365 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17366 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17367 if (fIOString)
17368 {
17369 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17370 if (fVmxInsOutsInfo)
17371 {
17372 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17373 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17374 }
17375 }
17376 AssertRCReturn(rc, rc);
17377
17378 VMXVEXITINFO ExitInfo;
17379 RT_ZERO(ExitInfo);
17380 ExitInfo.uReason = pVmxTransient->uExitReason;
17381 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17382 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17383 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17384 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17385 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17386 }
17387 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17388}
17389
17390
17391/**
17392 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17393 */
17394HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17395{
17396 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17397
17398 uint32_t fMsrpm;
17399 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17400 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17401 else
17402 fMsrpm = VMXMSRPM_EXIT_RD;
17403
17404 if (fMsrpm & VMXMSRPM_EXIT_RD)
17405 {
17406 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17407 AssertRCReturn(rc, rc);
17408 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17409 }
17410 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17411}
17412
17413
17414/**
17415 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17416 */
17417HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17418{
17419 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17420
17421 uint32_t fMsrpm;
17422 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17423 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17424 else
17425 fMsrpm = VMXMSRPM_EXIT_WR;
17426
17427 if (fMsrpm & VMXMSRPM_EXIT_WR)
17428 {
17429 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17430 AssertRCReturn(rc, rc);
17431 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17432 }
17433 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17434}
17435
17436
17437/**
17438 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17439 */
17440HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17441{
17442 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17443
17444 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17445 {
17446 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17447 AssertRCReturn(rc, rc);
17448 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17449 }
17450 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17451}
17452
17453
17454/**
17455 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17456 * VM-exit.
17457 */
17458HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17459{
17460 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17461
17462 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17463 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17464}
17465
17466
17467/**
17468 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17469 */
17470HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17471{
17472 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17473
17474 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17475 {
17476 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17477 AssertRCReturn(rc, rc);
17478 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17479 }
17480 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17481}
17482
17483
17484/**
17485 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17486 */
17487HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17488{
17489 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17490
17491 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17492 * PAUSE when executing a nested-guest? If it does not, we would not need
17493 * to check for the intercepts here. Just call VM-exit... */
17494
17495 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17496 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17497 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17498 {
17499 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17500 AssertRCReturn(rc, rc);
17501 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17502 }
17503 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17504}
17505
17506
17507/**
17508 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17509 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17510 */
17511HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17512{
17513 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17514
17515 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17516 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17517 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17518}
17519
17520
17521/**
17522 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17523 * VM-exit.
17524 */
17525HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17526{
17527 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17528
17529 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17530 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17531 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17532 AssertRCReturn(rc, rc);
17533
17534 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17535 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17536 AssertRCReturn(rc, rc);
17537
17538 VMXVEXITINFO ExitInfo;
17539 RT_ZERO(ExitInfo);
17540 ExitInfo.uReason = pVmxTransient->uExitReason;
17541 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17542 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17543
17544 VMXVEXITEVENTINFO ExitEventInfo;
17545 RT_ZERO(ExitEventInfo);
17546 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17547 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17548 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17549}
17550
17551
17552/**
17553 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17554 * Conditional VM-exit.
17555 */
17556HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17557{
17558 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17559
17560 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17561 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17562 AssertRCReturn(rc, rc);
17563
17564 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17565}
17566
17567
17568/**
17569 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17570 * Conditional VM-exit.
17571 */
17572HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17573{
17574 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17575
17576 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17577 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17578 AssertRCReturn(rc, rc);
17579
17580 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17581}
17582
17583
17584/**
17585 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17586 */
17587HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17588{
17589 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17590
17591 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17592 {
17593 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17594 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17595 AssertRCReturn(rc, rc);
17596 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17597 }
17598 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17599}
17600
17601
17602/**
17603 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17604 */
17605HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17606{
17607 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17608
17609 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17610 {
17611 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17612 AssertRCReturn(rc, rc);
17613 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17614 }
17615 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17616}
17617
17618
17619/**
17620 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17621 */
17622HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17623{
17624 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17625
17626 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17627 {
17628 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17629 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17630 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17631 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17632 AssertRCReturn(rc, rc);
17633
17634 VMXVEXITINFO ExitInfo;
17635 RT_ZERO(ExitInfo);
17636 ExitInfo.uReason = pVmxTransient->uExitReason;
17637 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17638 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17639 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17640 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17641 }
17642 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17643}
17644
17645
17646/**
17647 * Nested-guest VM-exit handler for invalid-guest state
17648 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17649 */
17650HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17651{
17652 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17653
17654 /*
17655 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17656 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17657 * Handle it like it's in an invalid guest state of the outer guest.
17658 *
17659 * When the fast path is implemented, this should be changed to cause the corresponding
17660 * nested-guest VM-exit.
17661 */
17662 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17663}
17664
17665
17666/**
17667 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17668 * and only provide the instruction length.
17669 *
17670 * Unconditional VM-exit.
17671 */
17672HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17673{
17674 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17675
17676#ifdef VBOX_STRICT
17677 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17678 switch (pVmxTransient->uExitReason)
17679 {
17680 case VMX_EXIT_ENCLS:
17681 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17682 break;
17683
17684 case VMX_EXIT_VMFUNC:
17685 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17686 break;
17687 }
17688#endif
17689
17690 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17691 AssertRCReturn(rc, rc);
17692 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17693}
17694
17695
17696/**
17697 * Nested-guest VM-exit handler for instructions that provide instruction length as
17698 * well as more information.
17699 *
17700 * Unconditional VM-exit.
17701 */
17702HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17703{
17704 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17705
17706#ifdef VBOX_STRICT
17707 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17708 switch (pVmxTransient->uExitReason)
17709 {
17710 case VMX_EXIT_GDTR_IDTR_ACCESS:
17711 case VMX_EXIT_LDTR_TR_ACCESS:
17712 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17713 break;
17714
17715 case VMX_EXIT_RDRAND:
17716 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17717 break;
17718
17719 case VMX_EXIT_RDSEED:
17720 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17721 break;
17722
17723 case VMX_EXIT_XSAVES:
17724 case VMX_EXIT_XRSTORS:
17725 /** @todo NSTVMX: Verify XSS-bitmap. */
17726 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17727 break;
17728
17729 case VMX_EXIT_UMWAIT:
17730 case VMX_EXIT_TPAUSE:
17731 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17732 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17733 break;
17734 }
17735#endif
17736
17737 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17738 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17739 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17740 AssertRCReturn(rc, rc);
17741
17742 VMXVEXITINFO ExitInfo;
17743 RT_ZERO(ExitInfo);
17744 ExitInfo.uReason = pVmxTransient->uExitReason;
17745 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17746 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17747 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17748 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17749}
17750
17751/** @} */
17752#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17753
Note: See TracBrowser for help on using the repository browser.

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