VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Fix exception handling. If a guest hypervisor is intercepting an exception, always forward IDT-vectoring info. as part of the VM-exit (i.e. those generated by hardware or by injected by guest hypervisor VMLAUNCH/VMRESUME).

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 729.9 KB
Line 
1/* $Id: HMVMXR0.cpp 79783 2019-07-15 10:45: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 Log4(("VM-exit: vcpu[%RU32] reason=%#x -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v\n", \
181 (a_pVCpu)->idCpu, (a_uExitReason))); \
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 LogFlowFunc(("MSR added, cMsrs now %u\n", 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 {
9365 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0/* uVector */, true /* fIntPending */);
9366 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9367 return rcStrict;
9368 }
9369#endif
9370 uint8_t u8Interrupt;
9371 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9372 if (RT_SUCCESS(rc))
9373 {
9374#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9375 if ( fIsNestedGuest
9376 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9377 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9378 {
9379 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9380 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9381 return rcStrict;
9382 }
9383#endif
9384 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9385 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9386 }
9387 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9388 {
9389 if ( !fIsNestedGuest
9390 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9391 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9392 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9393
9394 /*
9395 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9396 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9397 * need to re-set this force-flag here.
9398 */
9399 }
9400 else
9401 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9402 }
9403 else if (!fIsNestedGuest)
9404 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9405 }
9406
9407 return VINF_SUCCESS;
9408}
9409
9410
9411/**
9412 * Injects any pending events into the guest if the guest is in a state to
9413 * receive them.
9414 *
9415 * @returns Strict VBox status code (i.e. informational status codes too).
9416 * @param pVCpu The cross context virtual CPU structure.
9417 * @param pVmxTransient The VMX-transient structure.
9418 * @param fIntrState The VT-x guest-interruptibility state.
9419 * @param fStepping Whether we are single-stepping the guest using the
9420 * hypervisor debugger and should return
9421 * VINF_EM_DBG_STEPPED if the event was dispatched
9422 * directly.
9423 */
9424static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9425{
9426 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9427 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9428
9429 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9430 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9431
9432 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9433 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9434 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9435 Assert(!TRPMHasTrap(pVCpu));
9436
9437 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9438 if (pVCpu->hm.s.Event.fPending)
9439 {
9440 /*
9441 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9442 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9443 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9444 *
9445 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9446 */
9447 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9448#ifdef VBOX_STRICT
9449 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9450 {
9451 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9452 Assert(!fBlockInt);
9453 Assert(!fBlockSti);
9454 Assert(!fBlockMovSS);
9455 }
9456 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9457 {
9458 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9459 Assert(!fBlockSti);
9460 Assert(!fBlockMovSS);
9461 Assert(!fBlockNmi);
9462 }
9463#endif
9464 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9465 uIntType));
9466
9467 /*
9468 * Inject the event and get any changes to the guest-interruptibility state.
9469 *
9470 * The guest-interruptibility state may need to be updated if we inject the event
9471 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9472 */
9473 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9474 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9475
9476 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9477 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9478 else
9479 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9480 }
9481
9482 /*
9483 * Update the guest-interruptibility state.
9484 *
9485 * This is required for the real-on-v86 software interrupt injection case above, as well as
9486 * updates to the guest state from ring-3 or IEM/REM.
9487 */
9488 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9489 AssertRCReturn(rc, rc);
9490
9491 /*
9492 * There's no need to clear the VM-entry interruption-information field here if we're not
9493 * injecting anything. VT-x clears the valid bit on every VM-exit.
9494 *
9495 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9496 */
9497
9498 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9499 NOREF(fBlockMovSS); NOREF(fBlockSti);
9500 return rcStrict;
9501}
9502
9503
9504/**
9505 * Enters the VT-x session.
9506 *
9507 * @returns VBox status code.
9508 * @param pVCpu The cross context virtual CPU structure.
9509 */
9510VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9511{
9512 AssertPtr(pVCpu);
9513 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9514 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9515
9516 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9517 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9518 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9519
9520#ifdef VBOX_STRICT
9521 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9522 RTCCUINTREG uHostCr4 = ASMGetCR4();
9523 if (!(uHostCr4 & X86_CR4_VMXE))
9524 {
9525 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9526 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9527 }
9528#endif
9529
9530 /*
9531 * Load the appropriate VMCS as the current and active one.
9532 */
9533 PVMXVMCSINFO pVmcsInfo;
9534 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9535 if (!fInNestedGuestMode)
9536 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9537 else
9538 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9539 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9540 if (RT_SUCCESS(rc))
9541 {
9542 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9543 pVCpu->hm.s.fLeaveDone = false;
9544 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9545
9546 /*
9547 * Do the EMT scheduled L1D flush here if needed.
9548 */
9549 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9550 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9551 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9552 hmR0MdsClear();
9553 }
9554 return rc;
9555}
9556
9557
9558/**
9559 * The thread-context callback (only on platforms which support it).
9560 *
9561 * @param enmEvent The thread-context event.
9562 * @param pVCpu The cross context virtual CPU structure.
9563 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9564 * @thread EMT(pVCpu)
9565 */
9566VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9567{
9568 AssertPtr(pVCpu);
9569 RT_NOREF1(fGlobalInit);
9570
9571 switch (enmEvent)
9572 {
9573 case RTTHREADCTXEVENT_OUT:
9574 {
9575 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9576 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9577 VMCPU_ASSERT_EMT(pVCpu);
9578
9579 /* No longjmps (logger flushes, locks) in this fragile context. */
9580 VMMRZCallRing3Disable(pVCpu);
9581 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9582
9583 /* Restore host-state (FPU, debug etc.) */
9584 if (!pVCpu->hm.s.fLeaveDone)
9585 {
9586 /*
9587 * Do -not- import the guest-state here as we might already be in the middle of importing
9588 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9589 */
9590 hmR0VmxLeave(pVCpu, false /* fImportState */);
9591 pVCpu->hm.s.fLeaveDone = true;
9592 }
9593
9594 /* Leave HM context, takes care of local init (term). */
9595 int rc = HMR0LeaveCpu(pVCpu);
9596 AssertRC(rc);
9597
9598 /* Restore longjmp state. */
9599 VMMRZCallRing3Enable(pVCpu);
9600 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9601 break;
9602 }
9603
9604 case RTTHREADCTXEVENT_IN:
9605 {
9606 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9607 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9608 VMCPU_ASSERT_EMT(pVCpu);
9609
9610 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9611 VMMRZCallRing3Disable(pVCpu);
9612 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9613
9614 /* Initialize the bare minimum state required for HM. This takes care of
9615 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9616 int rc = hmR0EnterCpu(pVCpu);
9617 AssertRC(rc);
9618 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9619 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9620
9621 /* Load the active VMCS as the current one. */
9622 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9623 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9624 AssertRC(rc);
9625 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9626 pVCpu->hm.s.fLeaveDone = false;
9627
9628 /* Do the EMT scheduled L1D flush if needed. */
9629 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9630 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9631
9632 /* Restore longjmp state. */
9633 VMMRZCallRing3Enable(pVCpu);
9634 break;
9635 }
9636
9637 default:
9638 break;
9639 }
9640}
9641
9642
9643/**
9644 * Exports the host state into the VMCS host-state area.
9645 * Sets up the VM-exit MSR-load area.
9646 *
9647 * The CPU state will be loaded from these fields on every successful VM-exit.
9648 *
9649 * @returns VBox status code.
9650 * @param pVCpu The cross context virtual CPU structure.
9651 *
9652 * @remarks No-long-jump zone!!!
9653 */
9654static int hmR0VmxExportHostState(PVMCPU pVCpu)
9655{
9656 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9657
9658 int rc = VINF_SUCCESS;
9659 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9660 {
9661 rc = hmR0VmxExportHostControlRegs();
9662 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9663
9664 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9665 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9666
9667 rc = hmR0VmxExportHostMsrs(pVCpu);
9668 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9669
9670 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9671 }
9672 return rc;
9673}
9674
9675
9676/**
9677 * Saves the host state in the VMCS host-state.
9678 *
9679 * @returns VBox status code.
9680 * @param pVCpu The cross context virtual CPU structure.
9681 *
9682 * @remarks No-long-jump zone!!!
9683 */
9684VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9685{
9686 AssertPtr(pVCpu);
9687 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9688
9689 /*
9690 * Export the host state here while entering HM context.
9691 * When thread-context hooks are used, we might get preempted and have to re-save the host
9692 * state but most of the time we won't be, so do it here before we disable interrupts.
9693 */
9694 return hmR0VmxExportHostState(pVCpu);
9695}
9696
9697
9698/**
9699 * Exports the guest state into the VMCS guest-state area.
9700 *
9701 * The will typically be done before VM-entry when the guest-CPU state and the
9702 * VMCS state may potentially be out of sync.
9703 *
9704 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9705 * VM-entry controls.
9706 * Sets up the appropriate VMX non-root function to execute guest code based on
9707 * the guest CPU mode.
9708 *
9709 * @returns VBox strict status code.
9710 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9711 * without unrestricted guest execution and the VMMDev is not presently
9712 * mapped (e.g. EFI32).
9713 *
9714 * @param pVCpu The cross context virtual CPU structure.
9715 * @param pVmxTransient The VMX-transient structure.
9716 *
9717 * @remarks No-long-jump zone!!!
9718 */
9719static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9720{
9721 AssertPtr(pVCpu);
9722 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9723 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9724
9725 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9726
9727 /*
9728 * Determine real-on-v86 mode.
9729 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9730 */
9731 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9732 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9733 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9734 pVmcsInfo->RealMode. fRealOnV86Active = false;
9735 else
9736 {
9737 Assert(!pVmxTransient->fIsNestedGuest);
9738 pVmcsInfo->RealMode.fRealOnV86Active = true;
9739 }
9740
9741 /*
9742 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9743 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9744 */
9745 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9746 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9747 * be a need to evaluate this everytime since I'm pretty sure we intercept
9748 * all guest paging mode changes. */
9749 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9750 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9751
9752 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9753 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9754
9755 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9756 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9757
9758 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9759 if (rcStrict == VINF_SUCCESS)
9760 { /* likely */ }
9761 else
9762 {
9763 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9764 return rcStrict;
9765 }
9766
9767 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9768 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9769
9770 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9771 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9772
9773 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9774 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9775
9776 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9777 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9778
9779 rc = hmR0VmxExportGuestRip(pVCpu);
9780 rc |= hmR0VmxExportGuestRsp(pVCpu);
9781 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9782 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9783
9784 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9785 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9786
9787 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9788 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9789 | HM_CHANGED_GUEST_CR2
9790 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9791 | HM_CHANGED_GUEST_X87
9792 | HM_CHANGED_GUEST_SSE_AVX
9793 | HM_CHANGED_GUEST_OTHER_XSAVE
9794 | HM_CHANGED_GUEST_XCRx
9795 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9796 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9797 | HM_CHANGED_GUEST_TSC_AUX
9798 | HM_CHANGED_GUEST_OTHER_MSRS
9799 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9800
9801 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9802 return rc;
9803}
9804
9805
9806/**
9807 * Exports the state shared between the host and guest into the VMCS.
9808 *
9809 * @param pVCpu The cross context virtual CPU structure.
9810 * @param pVmxTransient The VMX-transient structure.
9811 *
9812 * @remarks No-long-jump zone!!!
9813 */
9814static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9815{
9816 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9817 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9818
9819 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9820 {
9821 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9822 AssertRC(rc);
9823 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9824
9825 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9826 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9827 {
9828 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9829 AssertRC(rc);
9830 }
9831 }
9832
9833 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9834 {
9835 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9836 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9837 }
9838
9839 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9840 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9841}
9842
9843
9844/**
9845 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9846 *
9847 * @returns Strict VBox status code (i.e. informational status codes too).
9848 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9849 * without unrestricted guest execution and the VMMDev is not presently
9850 * mapped (e.g. EFI32).
9851 *
9852 * @param pVCpu The cross context virtual CPU structure.
9853 * @param pVmxTransient The VMX-transient structure.
9854 *
9855 * @remarks No-long-jump zone!!!
9856 */
9857static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9858{
9859 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9860 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9861 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9862
9863#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9864 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9865#endif
9866
9867 /*
9868 * For many exits it's only RIP that changes and hence try to export it first
9869 * without going through a lot of change flag checks.
9870 */
9871 VBOXSTRICTRC rcStrict;
9872 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9873 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9874 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9875 {
9876 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9877 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9878 { /* likely */}
9879 else
9880 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9881 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9882 }
9883 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9884 {
9885 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9886 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9887 { /* likely */}
9888 else
9889 {
9890 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9891 VBOXSTRICTRC_VAL(rcStrict)));
9892 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9893 return rcStrict;
9894 }
9895 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9896 }
9897 else
9898 rcStrict = VINF_SUCCESS;
9899
9900#ifdef VBOX_STRICT
9901 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9902 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9903 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9904 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9905 ("fCtxChanged=%#RX64\n", fCtxChanged));
9906#endif
9907 return rcStrict;
9908}
9909
9910
9911/**
9912 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9913 * and update error record fields accordingly.
9914 *
9915 * @returns VMX_IGS_* error codes.
9916 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9917 * wrong with the guest state.
9918 *
9919 * @param pVCpu The cross context virtual CPU structure.
9920 * @param pVmcsInfo The VMCS info. object.
9921 *
9922 * @remarks This function assumes our cache of the VMCS controls
9923 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9924 */
9925static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9926{
9927#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9928#define HMVMX_CHECK_BREAK(expr, err) do { \
9929 if (!(expr)) { uError = (err); break; } \
9930 } while (0)
9931
9932 int rc;
9933 PVM pVM = pVCpu->CTX_SUFF(pVM);
9934 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9935 uint32_t uError = VMX_IGS_ERROR;
9936 uint32_t u32Val;
9937 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9938
9939 do
9940 {
9941 /*
9942 * CR0.
9943 */
9944 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9945 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9946 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9947 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9948 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9949 if (fUnrestrictedGuest)
9950 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
9951
9952 uint32_t u32GuestCr0;
9953 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
9954 AssertRCBreak(rc);
9955 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9956 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9957 if ( !fUnrestrictedGuest
9958 && (u32GuestCr0 & X86_CR0_PG)
9959 && !(u32GuestCr0 & X86_CR0_PE))
9960 {
9961 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9962 }
9963
9964 /*
9965 * CR4.
9966 */
9967 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9968 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9969 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9970
9971 uint32_t u32GuestCr4;
9972 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
9973 AssertRCBreak(rc);
9974 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9975 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9976
9977 /*
9978 * IA32_DEBUGCTL MSR.
9979 */
9980 uint64_t u64Val;
9981 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9982 AssertRCBreak(rc);
9983 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9984 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9985 {
9986 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9987 }
9988 uint64_t u64DebugCtlMsr = u64Val;
9989
9990#ifdef VBOX_STRICT
9991 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9992 AssertRCBreak(rc);
9993 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9994#endif
9995 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9996
9997 /*
9998 * RIP and RFLAGS.
9999 */
10000 uint32_t u32Eflags;
10001#if HC_ARCH_BITS == 64
10002 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10003 AssertRCBreak(rc);
10004 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10005 if ( !fLongModeGuest
10006 || !pCtx->cs.Attr.n.u1Long)
10007 {
10008 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10009 }
10010 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10011 * must be identical if the "IA-32e mode guest" VM-entry
10012 * control is 1 and CS.L is 1. No check applies if the
10013 * CPU supports 64 linear-address bits. */
10014
10015 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10016 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10017 AssertRCBreak(rc);
10018 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10019 VMX_IGS_RFLAGS_RESERVED);
10020 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10021 u32Eflags = u64Val;
10022#else
10023 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10024 AssertRCBreak(rc);
10025 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10026 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10027#endif
10028
10029 if ( fLongModeGuest
10030 || ( fUnrestrictedGuest
10031 && !(u32GuestCr0 & X86_CR0_PE)))
10032 {
10033 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10034 }
10035
10036 uint32_t u32EntryInfo;
10037 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10038 AssertRCBreak(rc);
10039 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10040 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10041
10042 /*
10043 * 64-bit checks.
10044 */
10045#if HC_ARCH_BITS == 64
10046 if (fLongModeGuest)
10047 {
10048 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10049 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10050 }
10051
10052 if ( !fLongModeGuest
10053 && (u32GuestCr4 & X86_CR4_PCIDE))
10054 {
10055 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10056 }
10057
10058 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10059 * 51:32 beyond the processor's physical-address width are 0. */
10060
10061 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10062 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10063 {
10064 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10065 }
10066
10067 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10068 AssertRCBreak(rc);
10069 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10070
10071 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10072 AssertRCBreak(rc);
10073 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10074#endif
10075
10076 /*
10077 * PERF_GLOBAL MSR.
10078 */
10079 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10080 {
10081 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10082 AssertRCBreak(rc);
10083 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10084 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10085 }
10086
10087 /*
10088 * PAT MSR.
10089 */
10090 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10091 {
10092 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10093 AssertRCBreak(rc);
10094 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10095 for (unsigned i = 0; i < 8; i++)
10096 {
10097 uint8_t u8Val = (u64Val & 0xff);
10098 if ( u8Val != 0 /* UC */
10099 && u8Val != 1 /* WC */
10100 && u8Val != 4 /* WT */
10101 && u8Val != 5 /* WP */
10102 && u8Val != 6 /* WB */
10103 && u8Val != 7 /* UC- */)
10104 {
10105 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10106 }
10107 u64Val >>= 8;
10108 }
10109 }
10110
10111 /*
10112 * EFER MSR.
10113 */
10114 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10115 {
10116 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10117 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10118 AssertRCBreak(rc);
10119 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10120 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10121 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10122 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10123 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10124 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10125 * iemVmxVmentryCheckGuestState(). */
10126 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10127 || !(u32GuestCr0 & X86_CR0_PG)
10128 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10129 VMX_IGS_EFER_LMA_LME_MISMATCH);
10130 }
10131
10132 /*
10133 * Segment registers.
10134 */
10135 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10136 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10137 if (!(u32Eflags & X86_EFL_VM))
10138 {
10139 /* CS */
10140 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10141 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10142 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10143 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10144 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10145 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10146 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10147 /* CS cannot be loaded with NULL in protected mode. */
10148 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10149 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10150 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10151 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10152 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10153 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10154 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10155 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10156 else
10157 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10158
10159 /* SS */
10160 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10161 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10162 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10163 if ( !(pCtx->cr0 & X86_CR0_PE)
10164 || pCtx->cs.Attr.n.u4Type == 3)
10165 {
10166 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10167 }
10168 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10169 {
10170 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10171 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10172 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10173 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10174 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10175 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10176 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10177 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10178 }
10179
10180 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10181 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10182 {
10183 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10184 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10185 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10186 || pCtx->ds.Attr.n.u4Type > 11
10187 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10188 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10189 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10190 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10191 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10192 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10193 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10194 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10195 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10196 }
10197 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10198 {
10199 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10200 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10201 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10202 || pCtx->es.Attr.n.u4Type > 11
10203 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10204 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10205 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10206 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10207 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10208 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10209 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10210 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10211 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10212 }
10213 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10214 {
10215 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10216 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10217 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10218 || pCtx->fs.Attr.n.u4Type > 11
10219 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10220 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10221 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10222 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10223 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10224 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10225 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10226 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10227 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10228 }
10229 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10230 {
10231 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10232 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10233 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10234 || pCtx->gs.Attr.n.u4Type > 11
10235 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10236 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10237 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10238 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10239 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10240 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10241 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10242 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10243 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10244 }
10245 /* 64-bit capable CPUs. */
10246#if HC_ARCH_BITS == 64
10247 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10248 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10249 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10250 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10251 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10252 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10253 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10254 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10255 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10256 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10257 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10258#endif
10259 }
10260 else
10261 {
10262 /* V86 mode checks. */
10263 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10264 if (pVmcsInfo->RealMode.fRealOnV86Active)
10265 {
10266 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10267 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10268 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10269 }
10270 else
10271 {
10272 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10273 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10274 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10275 }
10276
10277 /* CS */
10278 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10279 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10280 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10281 /* SS */
10282 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10283 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10284 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10285 /* DS */
10286 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10287 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10288 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10289 /* ES */
10290 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10291 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10292 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10293 /* FS */
10294 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10295 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10296 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10297 /* GS */
10298 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10299 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10300 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10301 /* 64-bit capable CPUs. */
10302#if HC_ARCH_BITS == 64
10303 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10304 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10305 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10306 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10307 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10308 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10309 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10310 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10311 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10312 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10313 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10314#endif
10315 }
10316
10317 /*
10318 * TR.
10319 */
10320 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10321 /* 64-bit capable CPUs. */
10322#if HC_ARCH_BITS == 64
10323 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10324#endif
10325 if (fLongModeGuest)
10326 {
10327 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10328 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10329 }
10330 else
10331 {
10332 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10333 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10334 VMX_IGS_TR_ATTR_TYPE_INVALID);
10335 }
10336 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10337 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10338 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10339 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10340 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10341 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10342 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10343 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10344
10345 /*
10346 * GDTR and IDTR.
10347 */
10348#if HC_ARCH_BITS == 64
10349 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10350 AssertRCBreak(rc);
10351 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10352
10353 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10354 AssertRCBreak(rc);
10355 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10356#endif
10357
10358 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10359 AssertRCBreak(rc);
10360 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10361
10362 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10363 AssertRCBreak(rc);
10364 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10365
10366 /*
10367 * Guest Non-Register State.
10368 */
10369 /* Activity State. */
10370 uint32_t u32ActivityState;
10371 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10372 AssertRCBreak(rc);
10373 HMVMX_CHECK_BREAK( !u32ActivityState
10374 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10375 VMX_IGS_ACTIVITY_STATE_INVALID);
10376 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10377 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10378 uint32_t u32IntrState;
10379 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10380 AssertRCBreak(rc);
10381 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10382 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10383 {
10384 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10385 }
10386
10387 /** @todo Activity state and injecting interrupts. Left as a todo since we
10388 * currently don't use activity states but ACTIVE. */
10389
10390 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10391 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10392
10393 /* Guest interruptibility-state. */
10394 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10395 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10396 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10397 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10398 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10399 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10400 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10401 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10402 {
10403 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10404 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10405 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10406 }
10407 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10408 {
10409 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10410 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10411 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10412 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10413 }
10414 /** @todo Assumes the processor is not in SMM. */
10415 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10416 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10417 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10418 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10419 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10420 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10421 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10422 {
10423 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10424 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10425 }
10426
10427 /* Pending debug exceptions. */
10428#if HC_ARCH_BITS == 64
10429 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10430 AssertRCBreak(rc);
10431 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10432 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10433 u32Val = u64Val; /* For pending debug exceptions checks below. */
10434#else
10435 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10436 AssertRCBreak(rc);
10437 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10438 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10439#endif
10440
10441 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10442 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10443 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10444 {
10445 if ( (u32Eflags & X86_EFL_TF)
10446 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10447 {
10448 /* Bit 14 is PendingDebug.BS. */
10449 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10450 }
10451 if ( !(u32Eflags & X86_EFL_TF)
10452 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10453 {
10454 /* Bit 14 is PendingDebug.BS. */
10455 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10456 }
10457 }
10458
10459 /* VMCS link pointer. */
10460 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10461 AssertRCBreak(rc);
10462 if (u64Val != UINT64_C(0xffffffffffffffff))
10463 {
10464 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10465 /** @todo Bits beyond the processor's physical-address width MBZ. */
10466 /** @todo SMM checks. */
10467 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10468 Assert(pVmcsInfo->pvShadowVmcs);
10469 VMXVMCSREVID VmcsRevId;
10470 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10471 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10472 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10473 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10474 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10475 }
10476
10477 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10478 * not using nested paging? */
10479 if ( pVM->hm.s.fNestedPaging
10480 && !fLongModeGuest
10481 && CPUMIsGuestInPAEModeEx(pCtx))
10482 {
10483 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10484 AssertRCBreak(rc);
10485 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10486
10487 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10488 AssertRCBreak(rc);
10489 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10490
10491 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10492 AssertRCBreak(rc);
10493 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10494
10495 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10496 AssertRCBreak(rc);
10497 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10498 }
10499
10500 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10501 if (uError == VMX_IGS_ERROR)
10502 uError = VMX_IGS_REASON_NOT_FOUND;
10503 } while (0);
10504
10505 pVCpu->hm.s.u32HMError = uError;
10506 return uError;
10507
10508#undef HMVMX_ERROR_BREAK
10509#undef HMVMX_CHECK_BREAK
10510}
10511
10512
10513/**
10514 * Map the APIC-access page for virtualizing APIC accesses.
10515 *
10516 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10517 * this not done as part of exporting guest state, see @bugref{8721}.
10518 *
10519 * @returns VBox status code.
10520 * @param pVCpu The cross context virtual CPU structure.
10521 */
10522static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10523{
10524 PVM pVM = pVCpu->CTX_SUFF(pVM);
10525 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10526
10527 Assert(PDMHasApic(pVM));
10528 Assert(u64MsrApicBase);
10529
10530 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10531 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10532
10533 /* Unalias the existing mapping. */
10534 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10535 AssertRCReturn(rc, rc);
10536
10537 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10538 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10539 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10540 AssertRCReturn(rc, rc);
10541
10542 /* Update the per-VCPU cache of the APIC base MSR. */
10543 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10544 return VINF_SUCCESS;
10545}
10546
10547
10548/**
10549 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10550 * CPU.
10551 *
10552 * @param idCpu The ID for the CPU the function is called on.
10553 * @param pvUser1 Null, not used.
10554 * @param pvUser2 Null, not used.
10555 */
10556static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10557{
10558 RT_NOREF3(idCpu, pvUser1, pvUser2);
10559 VMXDispatchHostNmi();
10560}
10561
10562
10563/**
10564 * Dispatching an NMI on the host CPU that received it.
10565 *
10566 * @returns VBox status code.
10567 * @param pVCpu The cross context virtual CPU structure.
10568 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10569 * executing when receiving the host NMI in VMX non-root
10570 * operation.
10571 */
10572static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10573{
10574 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
10575
10576 /*
10577 * We don't want to delay dispatching the NMI any more than we have to. However,
10578 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10579 * after executing guest or nested-guest code for the following reasons:
10580 *
10581 * - We would need to perform VMREADs with interrupts disabled and is orders of
10582 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
10583 * supported by the host hypervisor.
10584 *
10585 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10586 * longer period of time just for handling an edge case like host NMIs which do
10587 * not occur nearly as frequently as other VM-exits.
10588 *
10589 * Let's cover the most likely scenario first. Check if we are on the target CPU
10590 * and dispatch the NMI right away. This should be much faster than calling into
10591 * RTMpOnSpecific() machinery.
10592 */
10593 bool fDispatched = false;
10594 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10595 if (idCpu == RTMpCpuId())
10596 {
10597 VMXDispatchHostNmi();
10598 fDispatched = true;
10599 }
10600 ASMSetFlags(fEFlags);
10601 if (fDispatched)
10602 {
10603 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10604 return VINF_SUCCESS;
10605 }
10606
10607 /*
10608 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10609 * there should be no race or recursion even if we are unlucky enough to be preempted
10610 * (to the target CPU) without dispatching the host NMI above.
10611 */
10612 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10613 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10614}
10615
10616
10617#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10618/**
10619 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10620 * nested-guest using hardware-assisted VMX.
10621 *
10622 * @param pVCpu The cross context virtual CPU structure.
10623 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10624 * @param pVmcsInfoGst The guest VMCS info. object.
10625 */
10626static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10627{
10628 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10629 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10630 Assert(pu64MsrBitmap);
10631
10632 /*
10633 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10634 * MSR that is intercepted by the guest is also intercepted while executing the
10635 * nested-guest using hardware-assisted VMX.
10636 *
10637 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10638 * nested-guest VM-exit even if the outer guest is not intercepting some
10639 * MSRs. We cannot assume the caller has initialized the nested-guest
10640 * MSR bitmap in this case.
10641 *
10642 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10643 * each VM-entry, hence initializing it once per-VM while setting up the
10644 * nested-guest VMCS is not sufficient.
10645 */
10646 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10647 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10648 {
10649 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10650 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10651 Assert(pu64MsrBitmapNstGst);
10652 Assert(pu64MsrBitmapGst);
10653
10654 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10655 for (uint32_t i = 0; i < cFrags; i++)
10656 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10657 }
10658 else
10659 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10660}
10661
10662
10663/**
10664 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10665 * hardware-assisted VMX execution of the nested-guest.
10666 *
10667 * For a guest, we don't modify these controls once we set up the VMCS and hence
10668 * this function is never called.
10669 *
10670 * For nested-guests since the guest hypervisor provides these controls on every
10671 * nested-guest VM-entry and could potentially change them everytime we need to
10672 * merge them before every nested-guest VM-entry.
10673 *
10674 * @returns VBox status code.
10675 * @param pVCpu The cross context virtual CPU structure.
10676 */
10677static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10678{
10679 PVM pVM = pVCpu->CTX_SUFF(pVM);
10680 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10681 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10682 Assert(pVmcsNstGst);
10683
10684 /*
10685 * Merge the controls with the requirements of the guest VMCS.
10686 *
10687 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10688 * VMCS with the features supported by the physical CPU as it's already done by the
10689 * VMLAUNCH/VMRESUME instruction emulation.
10690 *
10691 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10692 * derived from the VMX features supported by the physical CPU.
10693 */
10694
10695 /* Pin-based VM-execution controls. */
10696 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10697
10698 /* Processor-based VM-execution controls. */
10699 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10700 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10701 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10702 | VMX_PROC_CTLS_USE_TPR_SHADOW
10703 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10704
10705 /* Secondary processor-based VM-execution controls. */
10706 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10707 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10708 | VMX_PROC_CTLS2_INVPCID
10709 | VMX_PROC_CTLS2_VMCS_SHADOWING
10710 | VMX_PROC_CTLS2_RDTSCP
10711 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10712 | VMX_PROC_CTLS2_APIC_REG_VIRT
10713 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10714 | VMX_PROC_CTLS2_VMFUNC));
10715
10716 /*
10717 * VM-entry controls:
10718 * These controls contains state that depends on the nested-guest state (primarily
10719 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10720 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10721 * properly continue executing the nested-guest if the EFER MSR changes but does not
10722 * cause a nested-guest VM-exits.
10723 *
10724 * VM-exit controls:
10725 * These controls specify the host state on return. We cannot use the controls from
10726 * the guest hypervisor state as is as it would contain the guest state rather than
10727 * the host state. Since the host state is subject to change (e.g. preemption, trips
10728 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10729 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10730 *
10731 * VM-entry MSR-load:
10732 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10733 * context by the VMLAUNCH/VMRESUME instruction emulation.
10734 *
10735 * VM-exit MSR-store:
10736 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10737 * back into the VM-exit MSR-store area.
10738 *
10739 * VM-exit MSR-load areas:
10740 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10741 * can entirely ignore what the guest hypervisor wants to load here.
10742 */
10743
10744 /*
10745 * Exception bitmap.
10746 *
10747 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10748 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10749 * code more flexible if intercepting exceptions become more dynamic in the future we do
10750 * it as part of exporting the nested-guest state.
10751 */
10752 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10753
10754 /*
10755 * CR0/CR4 guest/host mask.
10756 *
10757 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10758 * cause VM-exits, so we need to merge them here.
10759 */
10760 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10761 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10762
10763 /*
10764 * Page-fault error-code mask and match.
10765 *
10766 * Although we require unrestricted guest execution (and thereby nested-paging) for
10767 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10768 * normally intercept #PFs, it might intercept them for debugging purposes.
10769 *
10770 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10771 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10772 */
10773 uint32_t u32XcptPFMask;
10774 uint32_t u32XcptPFMatch;
10775 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10776 {
10777 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10778 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10779 }
10780 else
10781 {
10782 u32XcptPFMask = 0;
10783 u32XcptPFMatch = 0;
10784 }
10785
10786 /*
10787 * Pause-Loop exiting.
10788 */
10789 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10790 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10791
10792 /*
10793 * I/O Bitmap.
10794 *
10795 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10796 * intercept all I/O port accesses.
10797 */
10798 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10799
10800 /*
10801 * VMCS shadowing.
10802 *
10803 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10804 * enabled while executing the nested-guest.
10805 */
10806 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10807
10808 /*
10809 * APIC-access page.
10810 *
10811 * The APIC-access page address has already been initialized while setting up the
10812 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it should
10813 * not be of any consequence to the host or to the guest for that matter, but we only
10814 * accept valid addresses verified by the VMLAUNCH/VMRESUME instruction emulation to keep
10815 * it simple.
10816 */
10817
10818 /*
10819 * Virtual-APIC page and TPR threshold.
10820 *
10821 * The virtual-APIC page has already been allocated (by CPUM during VM startup) and cached
10822 * from guest memory as part of VMLAUNCH/VMRESUME instruction emulation. The host physical
10823 * address has also been updated in the nested-guest VMCS.
10824 */
10825 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10826 RTHCPHYS HCPhysVirtApic;
10827 uint32_t u32TprThreshold;
10828 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10829 {
10830 HCPhysVirtApic = pVmcsInfoNstGst->HCPhysVirtApic;
10831 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10832 }
10833 else
10834 {
10835 HCPhysVirtApic = 0;
10836 u32TprThreshold = 0;
10837
10838 /*
10839 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10840 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10841 * be taken care of by EPT/shadow paging.
10842 */
10843 if (pVM->hm.s.fAllow64BitGuests)
10844 {
10845 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10846 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10847 }
10848 }
10849
10850 /*
10851 * Validate basic assumptions.
10852 */
10853 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10854 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10855 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10856
10857 /*
10858 * Commit it to the nested-guest VMCS.
10859 */
10860 int rc = VINF_SUCCESS;
10861 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10862 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10863 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10864 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10865 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10866 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10867 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10868 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10869 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10870 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10871 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10872 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10873 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10874 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10875 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10876 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10877 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10878 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10879 {
10880 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10881 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10882 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10883 }
10884 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10885 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, pVmcsInfoNstGst->HCPhysVirtApic);
10886 AssertRCReturn(rc, rc);
10887
10888 /*
10889 * Update the nested-guest VMCS cache.
10890 */
10891 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10892 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10893 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10894 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10895 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10896 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10897 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10898 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10899 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10900
10901 /*
10902 * MSR bitmap.
10903 *
10904 * The MSR bitmap address has already been initialized while setting up the nested-guest
10905 * VMCS, here we need to merge the MSR bitmaps.
10906 */
10907 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10908 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10909
10910 return VINF_SUCCESS;
10911}
10912#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10913
10914
10915/**
10916 * Does the preparations before executing guest code in VT-x.
10917 *
10918 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10919 * recompiler/IEM. We must be cautious what we do here regarding committing
10920 * guest-state information into the VMCS assuming we assuredly execute the
10921 * guest in VT-x mode.
10922 *
10923 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10924 * the common-state (TRPM/forceflags), we must undo those changes so that the
10925 * recompiler/IEM can (and should) use them when it resumes guest execution.
10926 * Otherwise such operations must be done when we can no longer exit to ring-3.
10927 *
10928 * @returns Strict VBox status code (i.e. informational status codes too).
10929 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10930 * have been disabled.
10931 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10932 * pending events).
10933 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10934 * double-fault into the guest.
10935 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10936 * dispatched directly.
10937 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10938 *
10939 * @param pVCpu The cross context virtual CPU structure.
10940 * @param pVmxTransient The VMX-transient structure.
10941 * @param fStepping Whether we are single-stepping the guest in the
10942 * hypervisor debugger. Makes us ignore some of the reasons
10943 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10944 * if event dispatching took place.
10945 */
10946static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10947{
10948 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10949
10950#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10951 if (pVmxTransient->fIsNestedGuest)
10952 {
10953 RT_NOREF2(pVCpu, fStepping);
10954 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10955 return VINF_EM_RESCHEDULE_REM;
10956 }
10957#endif
10958
10959#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10960 PGMRZDynMapFlushAutoSet(pVCpu);
10961#endif
10962
10963 /*
10964 * Check and process force flag actions, some of which might require us to go back to ring-3.
10965 */
10966 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10967 if (rcStrict == VINF_SUCCESS)
10968 { /* FFs don't get set all the time. */ }
10969 else
10970 return rcStrict;
10971
10972 /*
10973 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10974 */
10975 /** @todo Doing this from ring-3 after VM setup phase causes a
10976 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10977 * idea why atm. */
10978 PVM pVM = pVCpu->CTX_SUFF(pVM);
10979 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10980 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10981 && PDMHasApic(pVM))
10982 {
10983 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10984 AssertRCReturn(rc, rc);
10985 }
10986
10987#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10988 /*
10989 * Merge guest VMCS controls with the nested-guest VMCS controls.
10990 *
10991 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10992 * saved state), we should be okay with merging controls as we initialize the
10993 * guest VMCS controls as part of VM setup phase.
10994 */
10995 if ( pVmxTransient->fIsNestedGuest
10996 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10997 {
10998 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10999 AssertRCReturn(rc, rc);
11000 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
11001 }
11002#endif
11003
11004 /*
11005 * Evaluate events to be injected into the guest.
11006 *
11007 * Events in TRPM can be injected without inspecting the guest state.
11008 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11009 * guest to cause a VM-exit the next time they are ready to receive the event.
11010 *
11011 * With nested-guests, evaluating pending events may cause VM-exits.
11012 */
11013 if (TRPMHasTrap(pVCpu))
11014 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11015
11016 uint32_t fIntrState;
11017 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11018
11019#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11020 /*
11021 * While evaluating pending events if something failed (unlikely) or if we were
11022 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11023 */
11024 if (rcStrict != VINF_SUCCESS)
11025 return rcStrict;
11026 if ( pVmxTransient->fIsNestedGuest
11027 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11028 {
11029 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11030 return VINF_VMX_VMEXIT;
11031 }
11032#else
11033 Assert(rcStrict == VINF_SUCCESS);
11034#endif
11035
11036 /*
11037 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11038 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11039 * also result in triple-faulting the VM.
11040 *
11041 * With nested-guests, the above does not apply since unrestricted guest execution is a
11042 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11043 */
11044 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11045 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11046 { /* likely */ }
11047 else
11048 {
11049 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11050 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11051 return rcStrict;
11052 }
11053
11054 /*
11055 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11056 * import CR3 themselves. We will need to update them here, as even as late as the above
11057 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11058 * the below force flags to be set.
11059 */
11060 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11061 {
11062 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11063 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11064 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11065 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11066 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11067 }
11068 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11069 {
11070 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11071 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11072 }
11073
11074#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11075 /* Paranoia. */
11076 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11077#endif
11078
11079 /*
11080 * No longjmps to ring-3 from this point on!!!
11081 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11082 * This also disables flushing of the R0-logger instance (if any).
11083 */
11084 VMMRZCallRing3Disable(pVCpu);
11085
11086 /*
11087 * Export the guest state bits.
11088 *
11089 * We cannot perform longjmps while loading the guest state because we do not preserve the
11090 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11091 * CPU migration.
11092 *
11093 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11094 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11095 */
11096 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11097 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11098 { /* likely */ }
11099 else
11100 {
11101 VMMRZCallRing3Enable(pVCpu);
11102 return rcStrict;
11103 }
11104
11105 /*
11106 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11107 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11108 * preemption disabled for a while. Since this is purely to aid the
11109 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11110 * disable interrupt on NT.
11111 *
11112 * We need to check for force-flags that could've possible been altered since we last
11113 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11114 * see @bugref{6398}).
11115 *
11116 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11117 * to ring-3 before executing guest code.
11118 */
11119 pVmxTransient->fEFlags = ASMIntDisableFlags();
11120
11121 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11122 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11123 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11124 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11125 {
11126 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11127 {
11128#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11129 /*
11130 * If we are executing a nested-guest make sure that we should intercept subsequent
11131 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
11132 * the VM-exit instruction emulation happy.
11133 */
11134 if (pVmxTransient->fIsNestedGuest)
11135 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11136#endif
11137
11138 /*
11139 * We've injected any pending events. This is really the point of no return (to ring-3).
11140 *
11141 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11142 * returns from this function, so do -not- enable them here.
11143 */
11144 pVCpu->hm.s.Event.fPending = false;
11145 return VINF_SUCCESS;
11146 }
11147
11148 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11149 rcStrict = VINF_EM_RAW_INTERRUPT;
11150 }
11151 else
11152 {
11153 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11154 rcStrict = VINF_EM_RAW_TO_R3;
11155 }
11156
11157 ASMSetFlags(pVmxTransient->fEFlags);
11158 VMMRZCallRing3Enable(pVCpu);
11159
11160 return rcStrict;
11161}
11162
11163
11164/**
11165 * Final preparations before executing guest code using hardware-assisted VMX.
11166 *
11167 * We can no longer get preempted to a different host CPU and there are no returns
11168 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11169 * failures), this function is not intended to fail sans unrecoverable hardware
11170 * errors.
11171 *
11172 * @param pVCpu The cross context virtual CPU structure.
11173 * @param pVmxTransient The VMX-transient structure.
11174 *
11175 * @remarks Called with preemption disabled.
11176 * @remarks No-long-jump zone!!!
11177 */
11178static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11179{
11180 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11181 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11182 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11183 Assert(!pVCpu->hm.s.Event.fPending);
11184
11185 /*
11186 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11187 */
11188 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11189 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11190
11191 PVM pVM = pVCpu->CTX_SUFF(pVM);
11192 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11193 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11194 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11195
11196 if (!CPUMIsGuestFPUStateActive(pVCpu))
11197 {
11198 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11199 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11200 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11201 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11202 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11203 }
11204
11205 /*
11206 * Re-export the host state bits as we may've been preempted (only happens when
11207 * thread-context hooks are used or when the VM start function changes) or if
11208 * the host CR0 is modified while loading the guest FPU state above.
11209 *
11210 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11211 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11212 * see @bugref{8432}.
11213 *
11214 * This may also happen when switching to/from a nested-guest VMCS without leaving
11215 * ring-0.
11216 */
11217 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11218 {
11219 hmR0VmxExportHostState(pVCpu);
11220 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11221 }
11222 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11223
11224 /*
11225 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11226 */
11227 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11228 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11229 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11230
11231 /*
11232 * Store status of the shared guest/host debug state at the time of VM-entry.
11233 */
11234#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11235 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11236 {
11237 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11238 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11239 }
11240 else
11241#endif
11242 {
11243 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11244 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11245 }
11246
11247 /*
11248 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11249 * more than one conditional check. The post-run side of our code shall determine
11250 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11251 */
11252 if (pVmcsInfo->pbVirtApic)
11253 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11254
11255 /*
11256 * Update the host MSRs values in the VM-exit MSR-load area.
11257 */
11258 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11259 {
11260 if (pVmcsInfo->cExitMsrLoad > 0)
11261 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11262 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11263 }
11264
11265 /*
11266 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11267 * VMX-preemption timer based on the next virtual sync clock deadline.
11268 */
11269 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11270 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11271 {
11272 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11273 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11274 }
11275
11276 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11277 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11278 if (!fIsRdtscIntercepted)
11279 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11280 else
11281 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11282
11283 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11284 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11285 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11286 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11287 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11288
11289 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11290
11291 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11292 as we're about to start executing the guest . */
11293
11294 /*
11295 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11296 *
11297 * This is done this late as updating the TSC offsetting/preemption timer above
11298 * figures out if we can skip intercepting RDTSCP by calculating the number of
11299 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11300 */
11301 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11302 && !fIsRdtscIntercepted)
11303 {
11304 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11305
11306 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11307 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11308 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11309 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11310 AssertRC(rc);
11311 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11312 pVmxTransient->fRemoveTscAuxMsr = true;
11313 }
11314
11315#ifdef VBOX_STRICT
11316 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11317 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11318 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11319 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11320#endif
11321
11322#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11323 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11324 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11325 * see @bugref{9180#c54}. */
11326 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11327 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11328 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11329#endif
11330}
11331
11332
11333/**
11334 * First C routine invoked after running guest code using hardware-assisted VMX.
11335 *
11336 * @param pVCpu The cross context virtual CPU structure.
11337 * @param pVmxTransient The VMX-transient structure.
11338 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11339 *
11340 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11341 *
11342 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11343 * unconditionally when it is safe to do so.
11344 */
11345static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11346{
11347 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11348
11349 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11350 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11351 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11352 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11353 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11354 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11355
11356 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11357 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11358 {
11359 uint64_t uGstTsc;
11360 if (!pVmxTransient->fIsNestedGuest)
11361 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11362 else
11363 {
11364 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11365 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11366 }
11367 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11368 }
11369
11370 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11371 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11372 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11373
11374#if HC_ARCH_BITS == 64
11375 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11376#endif
11377#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11378 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11379 and we need to leave it alone here. */
11380 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11381 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11382#else
11383 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11384#endif
11385#ifdef VBOX_STRICT
11386 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11387#endif
11388 Assert(!ASMIntAreEnabled());
11389 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11390 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11391
11392#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11393 /*
11394 * Clean all the VMCS fields in the transient structure before reading
11395 * anything from the VMCS.
11396 */
11397 pVmxTransient->uExitReason = 0;
11398 pVmxTransient->uExitIntErrorCode = 0;
11399 pVmxTransient->uExitQual = 0;
11400 pVmxTransient->uGuestLinearAddr = 0;
11401 pVmxTransient->uExitIntInfo = 0;
11402 pVmxTransient->cbInstr = 0;
11403 pVmxTransient->ExitInstrInfo.u = 0;
11404 pVmxTransient->uEntryIntInfo = 0;
11405 pVmxTransient->uEntryXcptErrorCode = 0;
11406 pVmxTransient->cbEntryInstr = 0;
11407 pVmxTransient->uIdtVectoringInfo = 0;
11408 pVmxTransient->uIdtVectoringErrorCode = 0;
11409#endif
11410
11411 /*
11412 * Save the basic VM-exit reason and check if the VM-entry failed.
11413 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11414 */
11415 uint32_t uExitReason;
11416 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11417 AssertRC(rc);
11418 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11419 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11420
11421 /*
11422 * Log the VM-exit before logging anything else as otherwise it might be a
11423 * tad confusing what happens before and after the world-switch.
11424 */
11425 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11426
11427 /*
11428 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11429 * bitmap permissions, if it was added before VM-entry.
11430 */
11431 if (pVmxTransient->fRemoveTscAuxMsr)
11432 {
11433 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11434 pVmxTransient->fRemoveTscAuxMsr = false;
11435 }
11436
11437 /*
11438 * Check if VMLAUNCH/VMRESUME succeeded.
11439 * If this failed, we cause a guru meditation and cease further execution.
11440 *
11441 * However, if we are executing a nested-guest we might fail if we use the
11442 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11443 */
11444 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11445 {
11446 /*
11447 * Update the VM-exit history array here even if the VM-entry failed due to:
11448 * - Invalid guest state.
11449 * - MSR loading.
11450 * - Machine-check event.
11451 *
11452 * In any of the above cases we will still have a "valid" VM-exit reason
11453 * despite @a fVMEntryFailed being false.
11454 *
11455 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11456 *
11457 * Note! We don't have CS or RIP at this point. Will probably address that later
11458 * by amending the history entry added here.
11459 */
11460 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11461 UINT64_MAX, uHostTsc);
11462
11463 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11464 {
11465 VMMRZCallRing3Enable(pVCpu);
11466
11467 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11468 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11469
11470#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11471 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11472 AssertRC(rc);
11473#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11474 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11475 AssertRC(rc);
11476#else
11477 /*
11478 * Import the guest-interruptibility state always as we need it while evaluating
11479 * injecting events on re-entry.
11480 *
11481 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11482 * checking for real-mode while exporting the state because all bits that cause
11483 * mode changes wrt CR0 are intercepted.
11484 */
11485 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11486 AssertRC(rc);
11487#endif
11488
11489 /*
11490 * Sync the TPR shadow with our APIC state.
11491 *
11492 * With nested-guests, mark the virtual-APIC page as dirty so it can be synced
11493 * when performing the nested-guest VM-exit.
11494 */
11495 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11496 {
11497 if (!pVmxTransient->fIsNestedGuest)
11498 {
11499 Assert(pVmcsInfo->pbVirtApic);
11500 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11501 {
11502 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11503 AssertRC(rc);
11504 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11505 }
11506 }
11507 else
11508 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true;
11509 }
11510
11511 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11512 return;
11513 }
11514 }
11515#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11516 else if (pVmxTransient->fIsNestedGuest)
11517 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11518#endif
11519 else
11520 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11521
11522 VMMRZCallRing3Enable(pVCpu);
11523}
11524
11525
11526/**
11527 * Runs the guest code using hardware-assisted VMX the normal way.
11528 *
11529 * @returns VBox status code.
11530 * @param pVCpu The cross context virtual CPU structure.
11531 * @param pcLoops Pointer to the number of executed loops.
11532 */
11533static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11534{
11535 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11536 Assert(pcLoops);
11537 Assert(*pcLoops <= cMaxResumeLoops);
11538 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11539
11540#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11541 /*
11542 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11543 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11544 * guest VMCS while entering the VMX ring-0 session.
11545 */
11546 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11547 {
11548 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11549 if (RT_SUCCESS(rc))
11550 { /* likely */ }
11551 else
11552 {
11553 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11554 return rc;
11555 }
11556 }
11557#endif
11558
11559 VMXTRANSIENT VmxTransient;
11560 RT_ZERO(VmxTransient);
11561 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11562
11563 /* Paranoia. */
11564 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11565
11566 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11567 for (;;)
11568 {
11569 Assert(!HMR0SuspendPending());
11570 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11571 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11572
11573 /*
11574 * Preparatory work for running nested-guest code, this may force us to
11575 * return to ring-3.
11576 *
11577 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11578 */
11579 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11580 if (rcStrict != VINF_SUCCESS)
11581 break;
11582
11583 /* Interrupts are disabled at this point! */
11584 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11585 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11586 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11587 /* Interrupts are re-enabled at this point! */
11588
11589 /*
11590 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11591 */
11592 if (RT_SUCCESS(rcRun))
11593 { /* very likely */ }
11594 else
11595 {
11596 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11597 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11598 return rcRun;
11599 }
11600
11601 /*
11602 * Profile the VM-exit.
11603 */
11604 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11605 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11606 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11607 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11608 HMVMX_START_EXIT_DISPATCH_PROF();
11609
11610 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11611
11612 /*
11613 * Handle the VM-exit.
11614 */
11615#ifdef HMVMX_USE_FUNCTION_TABLE
11616 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11617#else
11618 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11619#endif
11620 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11621 if (rcStrict == VINF_SUCCESS)
11622 {
11623 if (++(*pcLoops) <= cMaxResumeLoops)
11624 continue;
11625 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11626 rcStrict = VINF_EM_RAW_INTERRUPT;
11627 }
11628 break;
11629 }
11630
11631 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11632 return rcStrict;
11633}
11634
11635
11636#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11637/**
11638 * Runs the nested-guest code using hardware-assisted VMX.
11639 *
11640 * @returns VBox status code.
11641 * @param pVCpu The cross context virtual CPU structure.
11642 * @param pcLoops Pointer to the number of executed loops.
11643 *
11644 * @sa hmR0VmxRunGuestCodeNormal.
11645 */
11646static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11647{
11648 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11649 Assert(pcLoops);
11650 Assert(*pcLoops <= cMaxResumeLoops);
11651 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11652
11653 /*
11654 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11655 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11656 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11657 */
11658 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11659 {
11660 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11661 if (RT_SUCCESS(rc))
11662 { /* likely */ }
11663 else
11664 {
11665 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11666 return rc;
11667 }
11668 }
11669
11670 VMXTRANSIENT VmxTransient;
11671 RT_ZERO(VmxTransient);
11672 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11673 VmxTransient.fIsNestedGuest = true;
11674
11675 /* Paranoia. */
11676 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11677
11678 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11679 for (;;)
11680 {
11681 Assert(!HMR0SuspendPending());
11682 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11683 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11684
11685 /*
11686 * Preparatory work for running guest code, this may force us to
11687 * return to ring-3.
11688 *
11689 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11690 */
11691 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11692 if (rcStrict != VINF_SUCCESS)
11693 break;
11694
11695 /* Interrupts are disabled at this point! */
11696 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11697 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11698 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11699 /* Interrupts are re-enabled at this point! */
11700
11701 /*
11702 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11703 */
11704 if (RT_SUCCESS(rcRun))
11705 { /* very likely */ }
11706 else
11707 {
11708 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11709 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11710 return rcRun;
11711 }
11712
11713 /*
11714 * Profile the VM-exit.
11715 */
11716 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11717 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11718 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11719 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11720 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11721 HMVMX_START_EXIT_DISPATCH_PROF();
11722
11723 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11724
11725 /*
11726 * Handle the VM-exit.
11727 */
11728 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11729 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11730 if (rcStrict == VINF_SUCCESS)
11731 {
11732 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11733 {
11734 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11735 rcStrict = VINF_VMX_VMEXIT;
11736 }
11737 else
11738 {
11739 if (++(*pcLoops) <= cMaxResumeLoops)
11740 continue;
11741 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11742 rcStrict = VINF_EM_RAW_INTERRUPT;
11743 }
11744 }
11745 else
11746 Assert(rcStrict != VINF_VMX_VMEXIT);
11747 break;
11748 }
11749
11750 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11751 return rcStrict;
11752}
11753#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11754
11755
11756/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11757 * probes.
11758 *
11759 * The following few functions and associated structure contains the bloat
11760 * necessary for providing detailed debug events and dtrace probes as well as
11761 * reliable host side single stepping. This works on the principle of
11762 * "subclassing" the normal execution loop and workers. We replace the loop
11763 * method completely and override selected helpers to add necessary adjustments
11764 * to their core operation.
11765 *
11766 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11767 * any performance for debug and analysis features.
11768 *
11769 * @{
11770 */
11771
11772/**
11773 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11774 * the debug run loop.
11775 */
11776typedef struct VMXRUNDBGSTATE
11777{
11778 /** The RIP we started executing at. This is for detecting that we stepped. */
11779 uint64_t uRipStart;
11780 /** The CS we started executing with. */
11781 uint16_t uCsStart;
11782
11783 /** Whether we've actually modified the 1st execution control field. */
11784 bool fModifiedProcCtls : 1;
11785 /** Whether we've actually modified the 2nd execution control field. */
11786 bool fModifiedProcCtls2 : 1;
11787 /** Whether we've actually modified the exception bitmap. */
11788 bool fModifiedXcptBitmap : 1;
11789
11790 /** We desire the modified the CR0 mask to be cleared. */
11791 bool fClearCr0Mask : 1;
11792 /** We desire the modified the CR4 mask to be cleared. */
11793 bool fClearCr4Mask : 1;
11794 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11795 uint32_t fCpe1Extra;
11796 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11797 uint32_t fCpe1Unwanted;
11798 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11799 uint32_t fCpe2Extra;
11800 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11801 uint32_t bmXcptExtra;
11802 /** The sequence number of the Dtrace provider settings the state was
11803 * configured against. */
11804 uint32_t uDtraceSettingsSeqNo;
11805 /** VM-exits to check (one bit per VM-exit). */
11806 uint32_t bmExitsToCheck[3];
11807
11808 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11809 uint32_t fProcCtlsInitial;
11810 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11811 uint32_t fProcCtls2Initial;
11812 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11813 uint32_t bmXcptInitial;
11814} VMXRUNDBGSTATE;
11815AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11816typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11817
11818
11819/**
11820 * Initializes the VMXRUNDBGSTATE structure.
11821 *
11822 * @param pVCpu The cross context virtual CPU structure of the
11823 * calling EMT.
11824 * @param pVmxTransient The VMX-transient structure.
11825 * @param pDbgState The debug state to initialize.
11826 */
11827static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11828{
11829 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11830 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11831
11832 pDbgState->fModifiedProcCtls = false;
11833 pDbgState->fModifiedProcCtls2 = false;
11834 pDbgState->fModifiedXcptBitmap = false;
11835 pDbgState->fClearCr0Mask = false;
11836 pDbgState->fClearCr4Mask = false;
11837 pDbgState->fCpe1Extra = 0;
11838 pDbgState->fCpe1Unwanted = 0;
11839 pDbgState->fCpe2Extra = 0;
11840 pDbgState->bmXcptExtra = 0;
11841 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11842 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11843 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11844}
11845
11846
11847/**
11848 * Updates the VMSC fields with changes requested by @a pDbgState.
11849 *
11850 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11851 * immediately before executing guest code, i.e. when interrupts are disabled.
11852 * We don't check status codes here as we cannot easily assert or return in the
11853 * latter case.
11854 *
11855 * @param pVCpu The cross context virtual CPU structure.
11856 * @param pVmxTransient The VMX-transient structure.
11857 * @param pDbgState The debug state.
11858 */
11859static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11860{
11861 /*
11862 * Ensure desired flags in VMCS control fields are set.
11863 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11864 *
11865 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11866 * there should be no stale data in pCtx at this point.
11867 */
11868 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11869 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11870 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11871 {
11872 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11873 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11874 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11875 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11876 pDbgState->fModifiedProcCtls = true;
11877 }
11878
11879 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11880 {
11881 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11882 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11883 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11884 pDbgState->fModifiedProcCtls2 = true;
11885 }
11886
11887 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11888 {
11889 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11890 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11891 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11892 pDbgState->fModifiedXcptBitmap = true;
11893 }
11894
11895 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11896 {
11897 pVmcsInfo->u64Cr0Mask = 0;
11898 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11899 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11900 }
11901
11902 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11903 {
11904 pVmcsInfo->u64Cr4Mask = 0;
11905 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11906 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11907 }
11908
11909 NOREF(pVCpu);
11910}
11911
11912
11913/**
11914 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11915 * re-entry next time around.
11916 *
11917 * @returns Strict VBox status code (i.e. informational status codes too).
11918 * @param pVCpu The cross context virtual CPU structure.
11919 * @param pVmxTransient The VMX-transient structure.
11920 * @param pDbgState The debug state.
11921 * @param rcStrict The return code from executing the guest using single
11922 * stepping.
11923 */
11924static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11925 VBOXSTRICTRC rcStrict)
11926{
11927 /*
11928 * Restore VM-exit control settings as we may not reenter this function the
11929 * next time around.
11930 */
11931 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11932
11933 /* We reload the initial value, trigger what we can of recalculations the
11934 next time around. From the looks of things, that's all that's required atm. */
11935 if (pDbgState->fModifiedProcCtls)
11936 {
11937 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11938 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11939 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11940 AssertRCReturn(rc2, rc2);
11941 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11942 }
11943
11944 /* We're currently the only ones messing with this one, so just restore the
11945 cached value and reload the field. */
11946 if ( pDbgState->fModifiedProcCtls2
11947 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11948 {
11949 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11950 AssertRCReturn(rc2, rc2);
11951 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11952 }
11953
11954 /* If we've modified the exception bitmap, we restore it and trigger
11955 reloading and partial recalculation the next time around. */
11956 if (pDbgState->fModifiedXcptBitmap)
11957 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11958
11959 return rcStrict;
11960}
11961
11962
11963/**
11964 * Configures VM-exit controls for current DBGF and DTrace settings.
11965 *
11966 * This updates @a pDbgState and the VMCS execution control fields to reflect
11967 * the necessary VM-exits demanded by DBGF and DTrace.
11968 *
11969 * @param pVCpu The cross context virtual CPU structure.
11970 * @param pVmxTransient The VMX-transient structure. May update
11971 * fUpdatedTscOffsettingAndPreemptTimer.
11972 * @param pDbgState The debug state.
11973 */
11974static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11975{
11976 /*
11977 * Take down the dtrace serial number so we can spot changes.
11978 */
11979 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11980 ASMCompilerBarrier();
11981
11982 /*
11983 * We'll rebuild most of the middle block of data members (holding the
11984 * current settings) as we go along here, so start by clearing it all.
11985 */
11986 pDbgState->bmXcptExtra = 0;
11987 pDbgState->fCpe1Extra = 0;
11988 pDbgState->fCpe1Unwanted = 0;
11989 pDbgState->fCpe2Extra = 0;
11990 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11991 pDbgState->bmExitsToCheck[i] = 0;
11992
11993 /*
11994 * Software interrupts (INT XXh) - no idea how to trigger these...
11995 */
11996 PVM pVM = pVCpu->CTX_SUFF(pVM);
11997 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11998 || VBOXVMM_INT_SOFTWARE_ENABLED())
11999 {
12000 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12001 }
12002
12003 /*
12004 * INT3 breakpoints - triggered by #BP exceptions.
12005 */
12006 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
12007 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12008
12009 /*
12010 * Exception bitmap and XCPT events+probes.
12011 */
12012 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
12013 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
12014 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
12015
12016 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
12017 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
12018 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12019 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
12020 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
12021 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
12022 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12023 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12024 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12025 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12026 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12027 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12028 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12029 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12030 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12031 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12032 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12033 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12034
12035 if (pDbgState->bmXcptExtra)
12036 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12037
12038 /*
12039 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12040 *
12041 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12042 * So, when adding/changing/removing please don't forget to update it.
12043 *
12044 * Some of the macros are picking up local variables to save horizontal space,
12045 * (being able to see it in a table is the lesser evil here).
12046 */
12047#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12048 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12049 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12050#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12051 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12052 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12053 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12054 } else do { } while (0)
12055#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12056 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12057 { \
12058 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12059 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12060 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12061 } else do { } while (0)
12062#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12063 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12064 { \
12065 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12066 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12067 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12068 } else do { } while (0)
12069#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12070 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12071 { \
12072 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12073 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12074 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12075 } else do { } while (0)
12076
12077 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12078 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12079 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12080 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12081 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12082
12083 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12084 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12085 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12086 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12087 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12088 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12089 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12090 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12091 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12092 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12093 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12094 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12095 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12096 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12097 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12098 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12099 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12100 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12101 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12102 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12103 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12104 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12105 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12106 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12107 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12108 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12109 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12110 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12111 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12112 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12113 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12114 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12115 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12116 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12117 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12118 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12119
12120 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12121 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12122 {
12123 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12124 | CPUMCTX_EXTRN_APIC_TPR);
12125 AssertRC(rc);
12126
12127#if 0 /** @todo fix me */
12128 pDbgState->fClearCr0Mask = true;
12129 pDbgState->fClearCr4Mask = true;
12130#endif
12131 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12132 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12133 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12134 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12135 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12136 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12137 require clearing here and in the loop if we start using it. */
12138 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12139 }
12140 else
12141 {
12142 if (pDbgState->fClearCr0Mask)
12143 {
12144 pDbgState->fClearCr0Mask = false;
12145 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12146 }
12147 if (pDbgState->fClearCr4Mask)
12148 {
12149 pDbgState->fClearCr4Mask = false;
12150 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12151 }
12152 }
12153 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12154 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12155
12156 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12157 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12158 {
12159 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12160 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12161 }
12162 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12163 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12164
12165 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12166 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12167 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12168 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12169 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12170 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12171 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12172 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12173#if 0 /** @todo too slow, fix handler. */
12174 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12175#endif
12176 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12177
12178 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12179 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12180 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12181 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12182 {
12183 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12184 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12185 }
12186 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12187 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12188 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12189 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12190
12191 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12192 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12193 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12194 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12195 {
12196 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12197 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12198 }
12199 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12200 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12201 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12202 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12203
12204 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12205 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12206 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12207 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12208 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12209 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12210 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12211 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12212 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12213 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12214 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12215 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12216 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12217 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12218 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12219 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12220 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12221 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12222 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12223 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12224 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12225 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12226
12227#undef IS_EITHER_ENABLED
12228#undef SET_ONLY_XBM_IF_EITHER_EN
12229#undef SET_CPE1_XBM_IF_EITHER_EN
12230#undef SET_CPEU_XBM_IF_EITHER_EN
12231#undef SET_CPE2_XBM_IF_EITHER_EN
12232
12233 /*
12234 * Sanitize the control stuff.
12235 */
12236 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12237 if (pDbgState->fCpe2Extra)
12238 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12239 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12240 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12241 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12242 {
12243 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12244 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12245 }
12246
12247 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12248 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12249 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12250 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12251}
12252
12253
12254/**
12255 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12256 * appropriate.
12257 *
12258 * The caller has checked the VM-exit against the
12259 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12260 * already, so we don't have to do that either.
12261 *
12262 * @returns Strict VBox status code (i.e. informational status codes too).
12263 * @param pVCpu The cross context virtual CPU structure.
12264 * @param pVmxTransient The VMX-transient structure.
12265 * @param uExitReason The VM-exit reason.
12266 *
12267 * @remarks The name of this function is displayed by dtrace, so keep it short
12268 * and to the point. No longer than 33 chars long, please.
12269 */
12270static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12271{
12272 /*
12273 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12274 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12275 *
12276 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12277 * does. Must add/change/remove both places. Same ordering, please.
12278 *
12279 * Added/removed events must also be reflected in the next section
12280 * where we dispatch dtrace events.
12281 */
12282 bool fDtrace1 = false;
12283 bool fDtrace2 = false;
12284 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12285 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12286 uint32_t uEventArg = 0;
12287#define SET_EXIT(a_EventSubName) \
12288 do { \
12289 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12290 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12291 } while (0)
12292#define SET_BOTH(a_EventSubName) \
12293 do { \
12294 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12295 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12296 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12297 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12298 } while (0)
12299 switch (uExitReason)
12300 {
12301 case VMX_EXIT_MTF:
12302 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12303
12304 case VMX_EXIT_XCPT_OR_NMI:
12305 {
12306 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12307 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12308 {
12309 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12310 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12311 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12312 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12313 {
12314 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12315 {
12316 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12317 uEventArg = pVmxTransient->uExitIntErrorCode;
12318 }
12319 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12320 switch (enmEvent1)
12321 {
12322 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12323 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12324 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12325 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12326 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12327 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12328 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12329 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12330 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12331 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12332 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12333 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12334 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12335 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12336 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12337 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12338 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12339 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12340 default: break;
12341 }
12342 }
12343 else
12344 AssertFailed();
12345 break;
12346
12347 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12348 uEventArg = idxVector;
12349 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12350 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12351 break;
12352 }
12353 break;
12354 }
12355
12356 case VMX_EXIT_TRIPLE_FAULT:
12357 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12358 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12359 break;
12360 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12361 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12362 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12363 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12364 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12365
12366 /* Instruction specific VM-exits: */
12367 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12368 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12369 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12370 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12371 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12372 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12373 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12374 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12375 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12376 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12377 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12378 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12379 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12380 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12381 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12382 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12383 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12384 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12385 case VMX_EXIT_MOV_CRX:
12386 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12387 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12388 SET_BOTH(CRX_READ);
12389 else
12390 SET_BOTH(CRX_WRITE);
12391 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12392 break;
12393 case VMX_EXIT_MOV_DRX:
12394 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12395 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12396 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12397 SET_BOTH(DRX_READ);
12398 else
12399 SET_BOTH(DRX_WRITE);
12400 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12401 break;
12402 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12403 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12404 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12405 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12406 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12407 case VMX_EXIT_GDTR_IDTR_ACCESS:
12408 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12409 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12410 {
12411 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12412 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12413 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12414 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12415 }
12416 break;
12417
12418 case VMX_EXIT_LDTR_TR_ACCESS:
12419 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12420 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12421 {
12422 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12423 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12424 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12425 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12426 }
12427 break;
12428
12429 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12430 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12431 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12432 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12433 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12434 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12435 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12436 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12437 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12438 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12439 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12440
12441 /* Events that aren't relevant at this point. */
12442 case VMX_EXIT_EXT_INT:
12443 case VMX_EXIT_INT_WINDOW:
12444 case VMX_EXIT_NMI_WINDOW:
12445 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12446 case VMX_EXIT_PREEMPT_TIMER:
12447 case VMX_EXIT_IO_INSTR:
12448 break;
12449
12450 /* Errors and unexpected events. */
12451 case VMX_EXIT_INIT_SIGNAL:
12452 case VMX_EXIT_SIPI:
12453 case VMX_EXIT_IO_SMI:
12454 case VMX_EXIT_SMI:
12455 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12456 case VMX_EXIT_ERR_MSR_LOAD:
12457 case VMX_EXIT_ERR_MACHINE_CHECK:
12458 case VMX_EXIT_PML_FULL:
12459 case VMX_EXIT_VIRTUALIZED_EOI:
12460 break;
12461
12462 default:
12463 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12464 break;
12465 }
12466#undef SET_BOTH
12467#undef SET_EXIT
12468
12469 /*
12470 * Dtrace tracepoints go first. We do them here at once so we don't
12471 * have to copy the guest state saving and stuff a few dozen times.
12472 * Down side is that we've got to repeat the switch, though this time
12473 * we use enmEvent since the probes are a subset of what DBGF does.
12474 */
12475 if (fDtrace1 || fDtrace2)
12476 {
12477 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12478 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12479 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12480 switch (enmEvent1)
12481 {
12482 /** @todo consider which extra parameters would be helpful for each probe. */
12483 case DBGFEVENT_END: break;
12484 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12485 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12486 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12487 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12488 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12489 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12490 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12491 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12492 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12493 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12494 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12495 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12496 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12497 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12498 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12499 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12500 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12501 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12502 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12503 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12504 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12505 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12506 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12507 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12508 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12509 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12510 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12511 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12512 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12513 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12514 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12515 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12516 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12517 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12518 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12519 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12520 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12521 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12522 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12523 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12524 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12525 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12526 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12527 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12528 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12529 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12530 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12531 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12532 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12533 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12534 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12535 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12536 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12537 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12538 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12539 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12540 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12541 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12542 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12543 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12544 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12545 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12546 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12547 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12548 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12549 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12550 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12551 }
12552 switch (enmEvent2)
12553 {
12554 /** @todo consider which extra parameters would be helpful for each probe. */
12555 case DBGFEVENT_END: break;
12556 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12557 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12558 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12559 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12560 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12561 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12562 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12563 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12564 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12565 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12566 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12567 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12568 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12569 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12570 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12571 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12572 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12573 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12574 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12575 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12576 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12577 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12578 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12579 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12580 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12581 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12582 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12583 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12584 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12585 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12586 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12587 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12588 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12589 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12590 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12591 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12592 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12593 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12594 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12595 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12596 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12597 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12598 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12599 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12600 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12601 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12602 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12603 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12604 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12605 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12606 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12607 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12608 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12609 }
12610 }
12611
12612 /*
12613 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12614 * the DBGF call will do a full check).
12615 *
12616 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12617 * Note! If we have to events, we prioritize the first, i.e. the instruction
12618 * one, in order to avoid event nesting.
12619 */
12620 PVM pVM = pVCpu->CTX_SUFF(pVM);
12621 if ( enmEvent1 != DBGFEVENT_END
12622 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12623 {
12624 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12625 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12626 if (rcStrict != VINF_SUCCESS)
12627 return rcStrict;
12628 }
12629 else if ( enmEvent2 != DBGFEVENT_END
12630 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12631 {
12632 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12633 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12634 if (rcStrict != VINF_SUCCESS)
12635 return rcStrict;
12636 }
12637
12638 return VINF_SUCCESS;
12639}
12640
12641
12642/**
12643 * Single-stepping VM-exit filtering.
12644 *
12645 * This is preprocessing the VM-exits and deciding whether we've gotten far
12646 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12647 * handling is performed.
12648 *
12649 * @returns Strict VBox status code (i.e. informational status codes too).
12650 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12651 * @param pVmxTransient The VMX-transient structure.
12652 * @param pDbgState The debug state.
12653 */
12654DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12655{
12656 /*
12657 * Expensive (saves context) generic dtrace VM-exit probe.
12658 */
12659 uint32_t const uExitReason = pVmxTransient->uExitReason;
12660 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12661 { /* more likely */ }
12662 else
12663 {
12664 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12665 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12666 AssertRC(rc);
12667 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12668 }
12669
12670 /*
12671 * Check for host NMI, just to get that out of the way.
12672 */
12673 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12674 { /* normally likely */ }
12675 else
12676 {
12677 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12678 AssertRCReturn(rc2, rc2);
12679 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12680 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12681 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12682 }
12683
12684 /*
12685 * Check for single stepping event if we're stepping.
12686 */
12687 if (pVCpu->hm.s.fSingleInstruction)
12688 {
12689 switch (uExitReason)
12690 {
12691 case VMX_EXIT_MTF:
12692 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12693
12694 /* Various events: */
12695 case VMX_EXIT_XCPT_OR_NMI:
12696 case VMX_EXIT_EXT_INT:
12697 case VMX_EXIT_TRIPLE_FAULT:
12698 case VMX_EXIT_INT_WINDOW:
12699 case VMX_EXIT_NMI_WINDOW:
12700 case VMX_EXIT_TASK_SWITCH:
12701 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12702 case VMX_EXIT_APIC_ACCESS:
12703 case VMX_EXIT_EPT_VIOLATION:
12704 case VMX_EXIT_EPT_MISCONFIG:
12705 case VMX_EXIT_PREEMPT_TIMER:
12706
12707 /* Instruction specific VM-exits: */
12708 case VMX_EXIT_CPUID:
12709 case VMX_EXIT_GETSEC:
12710 case VMX_EXIT_HLT:
12711 case VMX_EXIT_INVD:
12712 case VMX_EXIT_INVLPG:
12713 case VMX_EXIT_RDPMC:
12714 case VMX_EXIT_RDTSC:
12715 case VMX_EXIT_RSM:
12716 case VMX_EXIT_VMCALL:
12717 case VMX_EXIT_VMCLEAR:
12718 case VMX_EXIT_VMLAUNCH:
12719 case VMX_EXIT_VMPTRLD:
12720 case VMX_EXIT_VMPTRST:
12721 case VMX_EXIT_VMREAD:
12722 case VMX_EXIT_VMRESUME:
12723 case VMX_EXIT_VMWRITE:
12724 case VMX_EXIT_VMXOFF:
12725 case VMX_EXIT_VMXON:
12726 case VMX_EXIT_MOV_CRX:
12727 case VMX_EXIT_MOV_DRX:
12728 case VMX_EXIT_IO_INSTR:
12729 case VMX_EXIT_RDMSR:
12730 case VMX_EXIT_WRMSR:
12731 case VMX_EXIT_MWAIT:
12732 case VMX_EXIT_MONITOR:
12733 case VMX_EXIT_PAUSE:
12734 case VMX_EXIT_GDTR_IDTR_ACCESS:
12735 case VMX_EXIT_LDTR_TR_ACCESS:
12736 case VMX_EXIT_INVEPT:
12737 case VMX_EXIT_RDTSCP:
12738 case VMX_EXIT_INVVPID:
12739 case VMX_EXIT_WBINVD:
12740 case VMX_EXIT_XSETBV:
12741 case VMX_EXIT_RDRAND:
12742 case VMX_EXIT_INVPCID:
12743 case VMX_EXIT_VMFUNC:
12744 case VMX_EXIT_RDSEED:
12745 case VMX_EXIT_XSAVES:
12746 case VMX_EXIT_XRSTORS:
12747 {
12748 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12749 AssertRCReturn(rc, rc);
12750 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12751 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12752 return VINF_EM_DBG_STEPPED;
12753 break;
12754 }
12755
12756 /* Errors and unexpected events: */
12757 case VMX_EXIT_INIT_SIGNAL:
12758 case VMX_EXIT_SIPI:
12759 case VMX_EXIT_IO_SMI:
12760 case VMX_EXIT_SMI:
12761 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12762 case VMX_EXIT_ERR_MSR_LOAD:
12763 case VMX_EXIT_ERR_MACHINE_CHECK:
12764 case VMX_EXIT_PML_FULL:
12765 case VMX_EXIT_VIRTUALIZED_EOI:
12766 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12767 break;
12768
12769 default:
12770 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12771 break;
12772 }
12773 }
12774
12775 /*
12776 * Check for debugger event breakpoints and dtrace probes.
12777 */
12778 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12779 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12780 {
12781 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12782 if (rcStrict != VINF_SUCCESS)
12783 return rcStrict;
12784 }
12785
12786 /*
12787 * Normal processing.
12788 */
12789#ifdef HMVMX_USE_FUNCTION_TABLE
12790 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12791#else
12792 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12793#endif
12794}
12795
12796
12797/**
12798 * Single steps guest code using hardware-assisted VMX.
12799 *
12800 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12801 * but single-stepping through the hypervisor debugger.
12802 *
12803 * @returns Strict VBox status code (i.e. informational status codes too).
12804 * @param pVCpu The cross context virtual CPU structure.
12805 * @param pcLoops Pointer to the number of executed loops.
12806 *
12807 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12808 */
12809static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12810{
12811 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12812 Assert(pcLoops);
12813 Assert(*pcLoops <= cMaxResumeLoops);
12814
12815 VMXTRANSIENT VmxTransient;
12816 RT_ZERO(VmxTransient);
12817 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12818
12819 /* Set HMCPU indicators. */
12820 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12821 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12822 pVCpu->hm.s.fDebugWantRdTscExit = false;
12823 pVCpu->hm.s.fUsingDebugLoop = true;
12824
12825 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12826 VMXRUNDBGSTATE DbgState;
12827 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12828 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12829
12830 /*
12831 * The loop.
12832 */
12833 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12834 for (;;)
12835 {
12836 Assert(!HMR0SuspendPending());
12837 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12838 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12839 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12840
12841 /* Set up VM-execution controls the next two can respond to. */
12842 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12843
12844 /*
12845 * Preparatory work for running guest code, this may force us to
12846 * return to ring-3.
12847 *
12848 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12849 */
12850 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12851 if (rcStrict != VINF_SUCCESS)
12852 break;
12853
12854 /* Interrupts are disabled at this point! */
12855 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12856
12857 /* Override any obnoxious code in the above two calls. */
12858 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12859
12860 /*
12861 * Finally execute the guest.
12862 */
12863 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12864
12865 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12866 /* Interrupts are re-enabled at this point! */
12867
12868 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12869 if (RT_SUCCESS(rcRun))
12870 { /* very likely */ }
12871 else
12872 {
12873 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12874 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12875 return rcRun;
12876 }
12877
12878 /* Profile the VM-exit. */
12879 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12880 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12881 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12882 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12883 HMVMX_START_EXIT_DISPATCH_PROF();
12884
12885 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12886
12887 /*
12888 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12889 */
12890 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12891 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12892 if (rcStrict != VINF_SUCCESS)
12893 break;
12894 if (++(*pcLoops) > cMaxResumeLoops)
12895 {
12896 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12897 rcStrict = VINF_EM_RAW_INTERRUPT;
12898 break;
12899 }
12900
12901 /*
12902 * Stepping: Did the RIP change, if so, consider it a single step.
12903 * Otherwise, make sure one of the TFs gets set.
12904 */
12905 if (fStepping)
12906 {
12907 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12908 AssertRC(rc);
12909 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12910 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12911 {
12912 rcStrict = VINF_EM_DBG_STEPPED;
12913 break;
12914 }
12915 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12916 }
12917
12918 /*
12919 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12920 */
12921 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12922 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12923 }
12924
12925 /*
12926 * Clear the X86_EFL_TF if necessary.
12927 */
12928 if (pVCpu->hm.s.fClearTrapFlag)
12929 {
12930 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12931 AssertRC(rc);
12932 pVCpu->hm.s.fClearTrapFlag = false;
12933 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12934 }
12935 /** @todo there seems to be issues with the resume flag when the monitor trap
12936 * flag is pending without being used. Seen early in bios init when
12937 * accessing APIC page in protected mode. */
12938
12939 /*
12940 * Restore VM-exit control settings as we may not re-enter this function the
12941 * next time around.
12942 */
12943 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12944
12945 /* Restore HMCPU indicators. */
12946 pVCpu->hm.s.fUsingDebugLoop = false;
12947 pVCpu->hm.s.fDebugWantRdTscExit = false;
12948 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12949
12950 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12951 return rcStrict;
12952}
12953
12954
12955/** @} */
12956
12957
12958/**
12959 * Checks if any expensive dtrace probes are enabled and we should go to the
12960 * debug loop.
12961 *
12962 * @returns true if we should use debug loop, false if not.
12963 */
12964static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12965{
12966 /* It's probably faster to OR the raw 32-bit counter variables together.
12967 Since the variables are in an array and the probes are next to one
12968 another (more or less), we have good locality. So, better read
12969 eight-nine cache lines ever time and only have one conditional, than
12970 128+ conditionals, right? */
12971 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12972 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12973 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12974 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12975 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12976 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12977 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12978 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12979 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12980 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12981 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12982 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12983 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12984 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12985 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12986 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12987 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12988 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12989 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12990 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12991 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12992 ) != 0
12993 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12994 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12995 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12996 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12997 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12998 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12999 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
13000 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
13001 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
13002 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
13003 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
13004 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
13005 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
13006 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
13007 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
13008 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
13009 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
13010 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
13011 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
13012 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
13013 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
13014 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
13015 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
13016 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
13017 | VBOXVMM_INSTR_STR_ENABLED_RAW()
13018 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
13019 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
13020 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
13021 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
13022 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13023 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13024 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13025 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13026 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13027 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13028 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13029 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13030 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13031 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13032 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13033 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13034 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13035 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13036 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13037 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13038 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13039 ) != 0
13040 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13041 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13042 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13043 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13044 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13045 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13046 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13047 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13048 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13049 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13050 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13051 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13052 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13053 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13054 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13055 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13056 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13057 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13058 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13059 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13060 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13061 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13062 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13063 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13064 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13065 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13066 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13067 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13068 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13069 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13070 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13071 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13072 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13073 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13074 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13075 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13076 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13077 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13078 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13079 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13080 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13081 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13082 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13083 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13084 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13085 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13086 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13087 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13088 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13089 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13090 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13091 ) != 0;
13092}
13093
13094
13095/**
13096 * Runs the guest using hardware-assisted VMX.
13097 *
13098 * @returns Strict VBox status code (i.e. informational status codes too).
13099 * @param pVCpu The cross context virtual CPU structure.
13100 */
13101VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13102{
13103 AssertPtr(pVCpu);
13104 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13105 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13106 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13107 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13108
13109 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13110
13111 VBOXSTRICTRC rcStrict;
13112 uint32_t cLoops = 0;
13113 for (;;)
13114 {
13115#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13116 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13117#else
13118 bool const fInNestedGuestMode = false;
13119#endif
13120 if (!fInNestedGuestMode)
13121 {
13122 if ( !pVCpu->hm.s.fUseDebugLoop
13123 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13124 && !DBGFIsStepping(pVCpu)
13125 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13126 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13127 else
13128 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13129 }
13130#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13131 else
13132 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13133
13134 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13135 {
13136 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13137 continue;
13138 }
13139 if (rcStrict == VINF_VMX_VMEXIT)
13140 {
13141 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13142 continue;
13143 }
13144#endif
13145 break;
13146 }
13147
13148 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13149 switch (rcLoop)
13150 {
13151 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13152 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13153 }
13154
13155 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13156 if (RT_FAILURE(rc2))
13157 {
13158 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13159 rcStrict = rc2;
13160 }
13161 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13162 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13163 return rcStrict;
13164}
13165
13166
13167#ifndef HMVMX_USE_FUNCTION_TABLE
13168/**
13169 * Handles a guest VM-exit from hardware-assisted VMX execution.
13170 *
13171 * @returns Strict VBox status code (i.e. informational status codes too).
13172 * @param pVCpu The cross context virtual CPU structure.
13173 * @param pVmxTransient The VMX-transient structure.
13174 */
13175DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13176{
13177#ifdef DEBUG_ramshankar
13178#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13179 do { \
13180 if (a_fSave != 0) \
13181 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13182 VBOXSTRICTRC rcStrict = a_CallExpr; \
13183 if (a_fSave != 0) \
13184 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13185 return rcStrict; \
13186 } while (0)
13187#else
13188# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13189#endif
13190 uint32_t const uExitReason = pVmxTransient->uExitReason;
13191 switch (uExitReason)
13192 {
13193 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13194 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13195 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13196 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13197 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13198 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13199 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13200 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13201 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13202 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13203 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13204 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13205 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13206 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13207 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13208 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13209 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13210 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13211 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13212 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13213 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13214 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13215 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13216 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13217 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13218 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13219 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13220 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13221 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13222 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13223#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13224 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13225 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13226 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13227 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13228 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13229 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13230 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13231 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13232 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13233 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13234 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13235#else
13236 case VMX_EXIT_VMCLEAR:
13237 case VMX_EXIT_VMLAUNCH:
13238 case VMX_EXIT_VMPTRLD:
13239 case VMX_EXIT_VMPTRST:
13240 case VMX_EXIT_VMREAD:
13241 case VMX_EXIT_VMRESUME:
13242 case VMX_EXIT_VMWRITE:
13243 case VMX_EXIT_VMXOFF:
13244 case VMX_EXIT_VMXON:
13245 case VMX_EXIT_INVVPID:
13246 case VMX_EXIT_INVEPT:
13247 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13248#endif
13249
13250 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13251 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13252 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13253
13254 case VMX_EXIT_INIT_SIGNAL:
13255 case VMX_EXIT_SIPI:
13256 case VMX_EXIT_IO_SMI:
13257 case VMX_EXIT_SMI:
13258 case VMX_EXIT_ERR_MSR_LOAD:
13259 case VMX_EXIT_ERR_MACHINE_CHECK:
13260 case VMX_EXIT_PML_FULL:
13261 case VMX_EXIT_VIRTUALIZED_EOI:
13262 case VMX_EXIT_GDTR_IDTR_ACCESS:
13263 case VMX_EXIT_LDTR_TR_ACCESS:
13264 case VMX_EXIT_APIC_WRITE:
13265 case VMX_EXIT_RDRAND:
13266 case VMX_EXIT_RSM:
13267 case VMX_EXIT_VMFUNC:
13268 case VMX_EXIT_ENCLS:
13269 case VMX_EXIT_RDSEED:
13270 case VMX_EXIT_XSAVES:
13271 case VMX_EXIT_XRSTORS:
13272 case VMX_EXIT_UMWAIT:
13273 case VMX_EXIT_TPAUSE:
13274 default:
13275 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13276 }
13277#undef VMEXIT_CALL_RET
13278}
13279#endif /* !HMVMX_USE_FUNCTION_TABLE */
13280
13281
13282#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13283/**
13284 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13285 *
13286 * @returns Strict VBox status code (i.e. informational status codes too).
13287 * @param pVCpu The cross context virtual CPU structure.
13288 * @param pVmxTransient The VMX-transient structure.
13289 */
13290DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13291{
13292 uint32_t const uExitReason = pVmxTransient->uExitReason;
13293 switch (uExitReason)
13294 {
13295 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13296 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13297 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13298 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13299 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13300
13301 /*
13302 * We shouldn't direct host physical interrupts to the nested-guest.
13303 */
13304 case VMX_EXIT_EXT_INT:
13305 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13306
13307 /*
13308 * Instructions that cause VM-exits unconditionally or the condition is
13309 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13310 * happens, it's guaranteed to be a nested-guest VM-exit).
13311 *
13312 * - Provides VM-exit instruction length ONLY.
13313 */
13314 case VMX_EXIT_CPUID: /* Unconditional. */
13315 case VMX_EXIT_VMCALL:
13316 case VMX_EXIT_GETSEC:
13317 case VMX_EXIT_INVD:
13318 case VMX_EXIT_XSETBV:
13319 case VMX_EXIT_VMLAUNCH:
13320 case VMX_EXIT_VMRESUME:
13321 case VMX_EXIT_VMXOFF:
13322 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13323 case VMX_EXIT_VMFUNC:
13324 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13325
13326 /*
13327 * Instructions that cause VM-exits unconditionally or the condition is
13328 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13329 * happens, it's guaranteed to be a nested-guest VM-exit).
13330 *
13331 * - Provides VM-exit instruction length.
13332 * - Provides VM-exit information.
13333 * - Optionally provides Exit qualification.
13334 *
13335 * Since Exit qualification is 0 for all VM-exits where it is not
13336 * applicable, reading and passing it to the guest should produce
13337 * defined behavior.
13338 *
13339 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13340 */
13341 case VMX_EXIT_INVEPT: /* Unconditional. */
13342 case VMX_EXIT_INVVPID:
13343 case VMX_EXIT_VMCLEAR:
13344 case VMX_EXIT_VMPTRLD:
13345 case VMX_EXIT_VMPTRST:
13346 case VMX_EXIT_VMXON:
13347 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13348 case VMX_EXIT_LDTR_TR_ACCESS:
13349 case VMX_EXIT_RDRAND:
13350 case VMX_EXIT_RDSEED:
13351 case VMX_EXIT_XSAVES:
13352 case VMX_EXIT_XRSTORS:
13353 case VMX_EXIT_UMWAIT:
13354 case VMX_EXIT_TPAUSE:
13355 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13356
13357 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13358 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13359 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13360 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13361 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13362 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13363 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13364 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13365 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13366 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13367 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13368 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13369 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13370 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13371 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13372 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13373 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13374 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13375 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13376
13377 case VMX_EXIT_PREEMPT_TIMER:
13378 {
13379 /** @todo NSTVMX: Preempt timer. */
13380 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13381 }
13382
13383 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13384 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13385
13386 case VMX_EXIT_VMREAD:
13387 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13388
13389 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13390 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13391
13392 case VMX_EXIT_INIT_SIGNAL:
13393 case VMX_EXIT_SIPI:
13394 case VMX_EXIT_IO_SMI:
13395 case VMX_EXIT_SMI:
13396 case VMX_EXIT_ERR_MSR_LOAD:
13397 case VMX_EXIT_ERR_MACHINE_CHECK:
13398 case VMX_EXIT_PML_FULL:
13399 case VMX_EXIT_RSM:
13400 default:
13401 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13402 }
13403}
13404#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13405
13406
13407/** @name VM-exit helpers.
13408 * @{
13409 */
13410/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13411/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13412/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13413
13414/** Macro for VM-exits called unexpectedly. */
13415#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13416 do { \
13417 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13418 return VERR_VMX_UNEXPECTED_EXIT; \
13419 } while (0)
13420
13421#ifdef VBOX_STRICT
13422/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13423# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13424 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13425
13426# define HMVMX_ASSERT_PREEMPT_CPUID() \
13427 do { \
13428 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13429 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13430 } while (0)
13431
13432# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13433 do { \
13434 AssertPtr((a_pVCpu)); \
13435 AssertPtr((a_pVmxTransient)); \
13436 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13437 Assert((a_pVmxTransient)->pVmcsInfo); \
13438 Assert(ASMIntAreEnabled()); \
13439 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13440 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13441 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13442 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13443 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13444 HMVMX_ASSERT_PREEMPT_CPUID(); \
13445 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13446 } while (0)
13447
13448# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13449 do { \
13450 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13451 Assert((a_pVmxTransient)->fIsNestedGuest); \
13452 } while (0)
13453
13454# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13455 do { \
13456 Log4Func(("\n")); \
13457 } while (0)
13458#else
13459# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13460 do { \
13461 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13462 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13463 } while (0)
13464
13465# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13466 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13467
13468# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13469#endif
13470
13471#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13472/** Macro that does the necessary privilege checks and intercepted VM-exits for
13473 * guests that attempted to execute a VMX instruction. */
13474# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13475 do \
13476 { \
13477 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13478 if (rcStrictTmp == VINF_SUCCESS) \
13479 { /* likely */ } \
13480 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13481 { \
13482 Assert((a_pVCpu)->hm.s.Event.fPending); \
13483 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13484 return VINF_SUCCESS; \
13485 } \
13486 else \
13487 { \
13488 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13489 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13490 } \
13491 } while (0)
13492
13493/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13494# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13495 do \
13496 { \
13497 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13498 (a_pGCPtrEffAddr)); \
13499 if (rcStrictTmp == VINF_SUCCESS) \
13500 { /* likely */ } \
13501 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13502 { \
13503 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13504 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13505 NOREF(uXcptTmp); \
13506 return VINF_SUCCESS; \
13507 } \
13508 else \
13509 { \
13510 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13511 return rcStrictTmp; \
13512 } \
13513 } while (0)
13514#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13515
13516
13517/**
13518 * Advances the guest RIP by the specified number of bytes.
13519 *
13520 * @param pVCpu The cross context virtual CPU structure.
13521 * @param cbInstr Number of bytes to advance the RIP by.
13522 *
13523 * @remarks No-long-jump zone!!!
13524 */
13525DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13526{
13527 /* Advance the RIP. */
13528 pVCpu->cpum.GstCtx.rip += cbInstr;
13529 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13530
13531 /* Update interrupt inhibition. */
13532 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13533 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13534 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13535}
13536
13537
13538/**
13539 * Advances the guest RIP after reading it from the VMCS.
13540 *
13541 * @returns VBox status code, no informational status codes.
13542 * @param pVCpu The cross context virtual CPU structure.
13543 * @param pVmxTransient The VMX-transient structure.
13544 *
13545 * @remarks No-long-jump zone!!!
13546 */
13547static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13548{
13549 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13550 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13551 AssertRCReturn(rc, rc);
13552
13553 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13554 return VINF_SUCCESS;
13555}
13556
13557
13558/**
13559 * Handle a condition that occurred while delivering an event through the guest or
13560 * nested-guest IDT.
13561 *
13562 * @returns Strict VBox status code (i.e. informational status codes too).
13563 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13564 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13565 * to continue execution of the guest which will delivery the \#DF.
13566 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13567 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13568 *
13569 * @param pVCpu The cross context virtual CPU structure.
13570 * @param pVmxTransient The VMX-transient structure.
13571 *
13572 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13573 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
13574 * is due to an EPT violation, PML full or SPP-related event.
13575 *
13576 * @remarks No-long-jump zone!!!
13577 */
13578static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13579{
13580 Assert(!pVCpu->hm.s.Event.fPending);
13581 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13582 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13583 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13584 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13585 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
13586
13587 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13588 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13589 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13590 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13591 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13592 {
13593 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13594 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13595
13596 /*
13597 * If the event was a software interrupt (generated with INT n) or a software exception
13598 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13599 * can handle the VM-exit and continue guest execution which will re-execute the
13600 * instruction rather than re-injecting the exception, as that can cause premature
13601 * trips to ring-3 before injection and involve TRPM which currently has no way of
13602 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13603 * the problem).
13604 */
13605 IEMXCPTRAISE enmRaise;
13606 IEMXCPTRAISEINFO fRaiseInfo;
13607 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13608 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13609 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13610 {
13611 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13612 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13613 }
13614 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13615 {
13616 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13617 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13618 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13619
13620 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13621 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13622
13623 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13624
13625 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13626 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13627 {
13628 pVmxTransient->fVectoringPF = true;
13629 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13630 }
13631 }
13632 else
13633 {
13634 /*
13635 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13636 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13637 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13638 */
13639 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13640 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13641 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13642 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13643 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13644 }
13645
13646 /*
13647 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13648 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13649 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13650 * subsequent VM-entry would fail, see @bugref{7445}.
13651 *
13652 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13653 */
13654 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13655 && enmRaise == IEMXCPTRAISE_PREV_EVENT
13656 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13657 && CPUMIsGuestNmiBlocking(pVCpu))
13658 {
13659 CPUMSetGuestNmiBlocking(pVCpu, false);
13660 }
13661
13662 switch (enmRaise)
13663 {
13664 case IEMXCPTRAISE_CURRENT_XCPT:
13665 {
13666 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
13667 Assert(rcStrict == VINF_SUCCESS);
13668 break;
13669 }
13670
13671 case IEMXCPTRAISE_PREV_EVENT:
13672 {
13673 uint32_t u32ErrCode;
13674 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13675 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13676 else
13677 u32ErrCode = 0;
13678
13679 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13680 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13681 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13682 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13683
13684 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13685 pVCpu->hm.s.Event.u32ErrCode));
13686 Assert(rcStrict == VINF_SUCCESS);
13687 break;
13688 }
13689
13690 case IEMXCPTRAISE_REEXEC_INSTR:
13691 Assert(rcStrict == VINF_SUCCESS);
13692 break;
13693
13694 case IEMXCPTRAISE_DOUBLE_FAULT:
13695 {
13696 /*
13697 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13698 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13699 */
13700 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13701 {
13702 pVmxTransient->fVectoringDoublePF = true;
13703 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13704 pVCpu->cpum.GstCtx.cr2));
13705 rcStrict = VINF_SUCCESS;
13706 }
13707 else
13708 {
13709 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13710 hmR0VmxSetPendingXcptDF(pVCpu);
13711 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13712 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13713 rcStrict = VINF_HM_DOUBLE_FAULT;
13714 }
13715 break;
13716 }
13717
13718 case IEMXCPTRAISE_TRIPLE_FAULT:
13719 {
13720 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13721 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13722 rcStrict = VINF_EM_RESET;
13723 break;
13724 }
13725
13726 case IEMXCPTRAISE_CPU_HANG:
13727 {
13728 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13729 rcStrict = VERR_EM_GUEST_CPU_HANG;
13730 break;
13731 }
13732
13733 default:
13734 {
13735 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13736 rcStrict = VERR_VMX_IPE_2;
13737 break;
13738 }
13739 }
13740 }
13741 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13742 && !CPUMIsGuestNmiBlocking(pVCpu))
13743 {
13744 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13745 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13746 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13747 {
13748 /*
13749 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13750 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13751 * that NMIs remain blocked until the IRET execution is completed.
13752 *
13753 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13754 */
13755 CPUMSetGuestNmiBlocking(pVCpu, true);
13756 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13757 }
13758 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13759 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13760 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13761 {
13762 /*
13763 * Execution of IRET caused an EPT violation, page-modification log-full event or
13764 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13765 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13766 * that NMIs remain blocked until the IRET execution is completed.
13767 *
13768 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13769 */
13770 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13771 {
13772 CPUMSetGuestNmiBlocking(pVCpu, true);
13773 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13774 }
13775 }
13776 }
13777
13778 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13779 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13780 return rcStrict;
13781}
13782
13783
13784#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13785/**
13786 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13787 * guest attempting to execute a VMX instruction.
13788 *
13789 * @returns Strict VBox status code (i.e. informational status codes too).
13790 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13791 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13792 *
13793 * @param pVCpu The cross context virtual CPU structure.
13794 * @param uExitReason The VM-exit reason.
13795 *
13796 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13797 * @remarks No-long-jump zone!!!
13798 */
13799static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13800{
13801 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13802 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13803
13804 /*
13805 * The physical CPU would have already checked the CPU mode/code segment.
13806 * We shall just assert here for paranoia.
13807 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13808 */
13809 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13810 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13811 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13812
13813 if (uExitReason == VMX_EXIT_VMXON)
13814 {
13815 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13816
13817 /*
13818 * We check CR4.VMXE because it is required to be always set while in VMX operation
13819 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13820 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13821 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13822 */
13823 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13824 {
13825 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13826 hmR0VmxSetPendingXcptUD(pVCpu);
13827 return VINF_HM_PENDING_XCPT;
13828 }
13829 }
13830 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13831 {
13832 /*
13833 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13834 * (other than VMXON), we need to raise a #UD.
13835 */
13836 Log4Func(("Not in VMX root mode -> #UD\n"));
13837 hmR0VmxSetPendingXcptUD(pVCpu);
13838 return VINF_HM_PENDING_XCPT;
13839 }
13840
13841 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13842 return VINF_SUCCESS;
13843}
13844
13845/**
13846 * Decodes the memory operand of an instruction that caused a VM-exit.
13847 *
13848 * The Exit qualification field provides the displacement field for memory
13849 * operand instructions, if any.
13850 *
13851 * @returns Strict VBox status code (i.e. informational status codes too).
13852 * @retval VINF_SUCCESS if the operand was successfully decoded.
13853 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13854 * operand.
13855 * @param pVCpu The cross context virtual CPU structure.
13856 * @param uExitInstrInfo The VM-exit instruction information field.
13857 * @param enmMemAccess The memory operand's access type (read or write).
13858 * @param GCPtrDisp The instruction displacement field, if any. For
13859 * RIP-relative addressing pass RIP + displacement here.
13860 * @param pGCPtrMem Where to store the effective destination memory address.
13861 *
13862 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13863 * virtual-8086 mode hence skips those checks while verifying if the
13864 * segment is valid.
13865 */
13866static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13867 PRTGCPTR pGCPtrMem)
13868{
13869 Assert(pGCPtrMem);
13870 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13871 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13872 | CPUMCTX_EXTRN_CR0);
13873
13874 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13875 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13876 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13877
13878 VMXEXITINSTRINFO ExitInstrInfo;
13879 ExitInstrInfo.u = uExitInstrInfo;
13880 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13881 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13882 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13883 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13884 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13885 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13886 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13887 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13888 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13889
13890 /*
13891 * Validate instruction information.
13892 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13893 */
13894 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13895 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13896 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13897 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13898 AssertLogRelMsgReturn(fIsMemOperand,
13899 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13900
13901 /*
13902 * Compute the complete effective address.
13903 *
13904 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13905 * See AMD spec. 4.5.2 "Segment Registers".
13906 */
13907 RTGCPTR GCPtrMem = GCPtrDisp;
13908 if (fBaseRegValid)
13909 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13910 if (fIdxRegValid)
13911 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13912
13913 RTGCPTR const GCPtrOff = GCPtrMem;
13914 if ( !fIsLongMode
13915 || iSegReg >= X86_SREG_FS)
13916 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13917 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13918
13919 /*
13920 * Validate effective address.
13921 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13922 */
13923 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13924 Assert(cbAccess > 0);
13925 if (fIsLongMode)
13926 {
13927 if (X86_IS_CANONICAL(GCPtrMem))
13928 {
13929 *pGCPtrMem = GCPtrMem;
13930 return VINF_SUCCESS;
13931 }
13932
13933 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13934 * "Data Limit Checks in 64-bit Mode". */
13935 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13936 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13937 return VINF_HM_PENDING_XCPT;
13938 }
13939
13940 /*
13941 * This is a watered down version of iemMemApplySegment().
13942 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13943 * and segment CPL/DPL checks are skipped.
13944 */
13945 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13946 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13947 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13948
13949 /* Check if the segment is present and usable. */
13950 if ( pSel->Attr.n.u1Present
13951 && !pSel->Attr.n.u1Unusable)
13952 {
13953 Assert(pSel->Attr.n.u1DescType);
13954 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13955 {
13956 /* Check permissions for the data segment. */
13957 if ( enmMemAccess == VMXMEMACCESS_WRITE
13958 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13959 {
13960 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13961 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13962 return VINF_HM_PENDING_XCPT;
13963 }
13964
13965 /* Check limits if it's a normal data segment. */
13966 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13967 {
13968 if ( GCPtrFirst32 > pSel->u32Limit
13969 || GCPtrLast32 > pSel->u32Limit)
13970 {
13971 Log4Func(("Data segment limit exceeded. "
13972 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13973 GCPtrLast32, pSel->u32Limit));
13974 if (iSegReg == X86_SREG_SS)
13975 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13976 else
13977 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13978 return VINF_HM_PENDING_XCPT;
13979 }
13980 }
13981 else
13982 {
13983 /* Check limits if it's an expand-down data segment.
13984 Note! The upper boundary is defined by the B bit, not the G bit! */
13985 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13986 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13987 {
13988 Log4Func(("Expand-down data segment limit exceeded. "
13989 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13990 GCPtrLast32, pSel->u32Limit));
13991 if (iSegReg == X86_SREG_SS)
13992 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13993 else
13994 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13995 return VINF_HM_PENDING_XCPT;
13996 }
13997 }
13998 }
13999 else
14000 {
14001 /* Check permissions for the code segment. */
14002 if ( enmMemAccess == VMXMEMACCESS_WRITE
14003 || ( enmMemAccess == VMXMEMACCESS_READ
14004 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
14005 {
14006 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
14007 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
14008 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14009 return VINF_HM_PENDING_XCPT;
14010 }
14011
14012 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
14013 if ( GCPtrFirst32 > pSel->u32Limit
14014 || GCPtrLast32 > pSel->u32Limit)
14015 {
14016 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
14017 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
14018 if (iSegReg == X86_SREG_SS)
14019 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14020 else
14021 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14022 return VINF_HM_PENDING_XCPT;
14023 }
14024 }
14025 }
14026 else
14027 {
14028 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14029 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14030 return VINF_HM_PENDING_XCPT;
14031 }
14032
14033 *pGCPtrMem = GCPtrMem;
14034 return VINF_SUCCESS;
14035}
14036#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
14037
14038
14039/**
14040 * VM-exit helper for LMSW.
14041 */
14042static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
14043{
14044 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14045 AssertRCReturn(rc, rc);
14046
14047 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14048 AssertMsg( rcStrict == VINF_SUCCESS
14049 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14050
14051 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14052 if (rcStrict == VINF_IEM_RAISED_XCPT)
14053 {
14054 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14055 rcStrict = VINF_SUCCESS;
14056 }
14057
14058 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14059 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14060 return rcStrict;
14061}
14062
14063
14064/**
14065 * VM-exit helper for CLTS.
14066 */
14067static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14068{
14069 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14070 AssertRCReturn(rc, rc);
14071
14072 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14073 AssertMsg( rcStrict == VINF_SUCCESS
14074 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14075
14076 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14077 if (rcStrict == VINF_IEM_RAISED_XCPT)
14078 {
14079 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14080 rcStrict = VINF_SUCCESS;
14081 }
14082
14083 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14084 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14085 return rcStrict;
14086}
14087
14088
14089/**
14090 * VM-exit helper for MOV from CRx (CRx read).
14091 */
14092static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14093{
14094 Assert(iCrReg < 16);
14095 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14096
14097 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14098 AssertRCReturn(rc, rc);
14099
14100 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14101 AssertMsg( rcStrict == VINF_SUCCESS
14102 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14103
14104 if (iGReg == X86_GREG_xSP)
14105 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14106 else
14107 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14108#ifdef VBOX_WITH_STATISTICS
14109 switch (iCrReg)
14110 {
14111 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14112 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14113 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14114 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14115 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14116 }
14117#endif
14118 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14119 return rcStrict;
14120}
14121
14122
14123/**
14124 * VM-exit helper for MOV to CRx (CRx write).
14125 */
14126static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14127{
14128 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14129 AssertRCReturn(rc, rc);
14130
14131 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14132 AssertMsg( rcStrict == VINF_SUCCESS
14133 || rcStrict == VINF_IEM_RAISED_XCPT
14134 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14135
14136 switch (iCrReg)
14137 {
14138 case 0:
14139 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14140 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14141 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14142 break;
14143
14144 case 2:
14145 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14146 /* Nothing to do here, CR2 it's not part of the VMCS. */
14147 break;
14148
14149 case 3:
14150 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14151 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14152 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14153 break;
14154
14155 case 4:
14156 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14157 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14158 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14159 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14160 break;
14161
14162 case 8:
14163 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14164 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14165 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14166 break;
14167
14168 default:
14169 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14170 break;
14171 }
14172
14173 if (rcStrict == VINF_IEM_RAISED_XCPT)
14174 {
14175 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14176 rcStrict = VINF_SUCCESS;
14177 }
14178 return rcStrict;
14179}
14180
14181
14182/**
14183 * VM-exit exception handler for \#PF (Page-fault exception).
14184 *
14185 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14186 */
14187static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14188{
14189 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14190 PVM pVM = pVCpu->CTX_SUFF(pVM);
14191 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14192 AssertRCReturn(rc, rc);
14193
14194 if (!pVM->hm.s.fNestedPaging)
14195 { /* likely */ }
14196 else
14197 {
14198#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14199 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14200#endif
14201 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14202 if (!pVmxTransient->fVectoringDoublePF)
14203 {
14204 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14205 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14206 }
14207 else
14208 {
14209 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14210 Assert(!pVmxTransient->fIsNestedGuest);
14211 hmR0VmxSetPendingXcptDF(pVCpu);
14212 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14213 }
14214 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14215 return rc;
14216 }
14217
14218 Assert(!pVmxTransient->fIsNestedGuest);
14219
14220 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14221 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14222 if (pVmxTransient->fVectoringPF)
14223 {
14224 Assert(pVCpu->hm.s.Event.fPending);
14225 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14226 }
14227
14228 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14229 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14230 AssertRCReturn(rc, rc);
14231
14232 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14233 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14234
14235 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14236 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14237
14238 Log4Func(("#PF: rc=%Rrc\n", rc));
14239 if (rc == VINF_SUCCESS)
14240 {
14241 /*
14242 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14243 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14244 */
14245 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14246 TRPMResetTrap(pVCpu);
14247 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14248 return rc;
14249 }
14250
14251 if (rc == VINF_EM_RAW_GUEST_TRAP)
14252 {
14253 if (!pVmxTransient->fVectoringDoublePF)
14254 {
14255 /* It's a guest page fault and needs to be reflected to the guest. */
14256 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14257 TRPMResetTrap(pVCpu);
14258 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14259 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14260 uGstErrorCode, pVmxTransient->uExitQual);
14261 }
14262 else
14263 {
14264 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14265 TRPMResetTrap(pVCpu);
14266 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14267 hmR0VmxSetPendingXcptDF(pVCpu);
14268 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14269 }
14270
14271 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14272 return VINF_SUCCESS;
14273 }
14274
14275 TRPMResetTrap(pVCpu);
14276 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14277 return rc;
14278}
14279
14280
14281/**
14282 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14283 *
14284 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14285 */
14286static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14287{
14288 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14289 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14290
14291 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14292 AssertRCReturn(rc, rc);
14293
14294 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14295 {
14296 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14297 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14298
14299 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14300 * provides VM-exit instruction length. If this causes problem later,
14301 * disassemble the instruction like it's done on AMD-V. */
14302 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14303 AssertRCReturn(rc2, rc2);
14304 return rc;
14305 }
14306
14307 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14308 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14309 return VINF_SUCCESS;
14310}
14311
14312
14313/**
14314 * VM-exit exception handler for \#BP (Breakpoint exception).
14315 *
14316 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14317 */
14318static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14319{
14320 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14321 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14322
14323 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14324 AssertRCReturn(rc, rc);
14325
14326 if (!pVmxTransient->fIsNestedGuest)
14327 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14328 else
14329 rc = VINF_EM_RAW_GUEST_TRAP;
14330 if (rc == VINF_EM_RAW_GUEST_TRAP)
14331 {
14332 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14333 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14334 }
14335
14336 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14337 return rc;
14338}
14339
14340
14341/**
14342 * VM-exit exception handler for \#AC (Alignment-check exception).
14343 *
14344 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14345 */
14346static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14347{
14348 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14349 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14350
14351 /* Re-inject it. We'll detect any nesting before getting here. */
14352 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14353 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14354 return VINF_SUCCESS;
14355}
14356
14357
14358/**
14359 * VM-exit exception handler for \#DB (Debug exception).
14360 *
14361 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14362 */
14363static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14364{
14365 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14366 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14367
14368 /*
14369 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14370 */
14371 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14372 AssertRCReturn(rc, rc);
14373
14374 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14375 uint64_t const uDR6 = X86_DR6_INIT_VAL
14376 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14377 | X86_DR6_BD | X86_DR6_BS));
14378
14379 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14380 if (!pVmxTransient->fIsNestedGuest)
14381 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14382 else
14383 rc = VINF_EM_RAW_GUEST_TRAP;
14384 Log6Func(("rc=%Rrc\n", rc));
14385 if (rc == VINF_EM_RAW_GUEST_TRAP)
14386 {
14387 /*
14388 * The exception was for the guest. Update DR6, DR7.GD and
14389 * IA32_DEBUGCTL.LBR before forwarding it.
14390 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14391 */
14392 VMMRZCallRing3Disable(pVCpu);
14393 HM_DISABLE_PREEMPT(pVCpu);
14394
14395 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14396 pCtx->dr[6] |= uDR6;
14397 if (CPUMIsGuestDebugStateActive(pVCpu))
14398 ASMSetDR6(pCtx->dr[6]);
14399
14400 HM_RESTORE_PREEMPT();
14401 VMMRZCallRing3Enable(pVCpu);
14402
14403 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14404 AssertRCReturn(rc, rc);
14405
14406 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14407 pCtx->dr[7] &= ~X86_DR7_GD;
14408
14409 /* Paranoia. */
14410 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14411 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14412
14413 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14414 AssertRCReturn(rc, rc);
14415
14416 /*
14417 * Raise #DB in the guest.
14418 *
14419 * It is important to reflect exactly what the VM-exit gave us (preserving the
14420 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14421 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14422 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14423 *
14424 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14425 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14426 */
14427 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14428 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14429 return VINF_SUCCESS;
14430 }
14431
14432 /*
14433 * Not a guest trap, must be a hypervisor related debug event then.
14434 * Update DR6 in case someone is interested in it.
14435 */
14436 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14437 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14438 CPUMSetHyperDR6(pVCpu, uDR6);
14439
14440 return rc;
14441}
14442
14443
14444/**
14445 * Hacks its way around the lovely mesa driver's backdoor accesses.
14446 *
14447 * @sa hmR0SvmHandleMesaDrvGp.
14448 */
14449static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14450{
14451 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14452 RT_NOREF(pCtx);
14453
14454 /* For now we'll just skip the instruction. */
14455 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14456}
14457
14458
14459/**
14460 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14461 * backdoor logging w/o checking what it is running inside.
14462 *
14463 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14464 * backdoor port and magic numbers loaded in registers.
14465 *
14466 * @returns true if it is, false if it isn't.
14467 * @sa hmR0SvmIsMesaDrvGp.
14468 */
14469DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14470{
14471 /* 0xed: IN eAX,dx */
14472 uint8_t abInstr[1];
14473 if (pVmxTransient->cbInstr != sizeof(abInstr))
14474 return false;
14475
14476 /* Check that it is #GP(0). */
14477 if (pVmxTransient->uExitIntErrorCode != 0)
14478 return false;
14479
14480 /* Check magic and port. */
14481 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14482 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14483 if (pCtx->rax != UINT32_C(0x564d5868))
14484 return false;
14485 if (pCtx->dx != UINT32_C(0x5658))
14486 return false;
14487
14488 /* Flat ring-3 CS. */
14489 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14490 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14491 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14492 if (pCtx->cs.Attr.n.u2Dpl != 3)
14493 return false;
14494 if (pCtx->cs.u64Base != 0)
14495 return false;
14496
14497 /* Check opcode. */
14498 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14499 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14500 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14501 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14502 if (RT_FAILURE(rc))
14503 return false;
14504 if (abInstr[0] != 0xed)
14505 return false;
14506
14507 return true;
14508}
14509
14510
14511/**
14512 * VM-exit exception handler for \#GP (General-protection exception).
14513 *
14514 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14515 */
14516static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14517{
14518 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14519 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14520
14521 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14522 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14523 if (pVmcsInfo->RealMode.fRealOnV86Active)
14524 { /* likely */ }
14525 else
14526 {
14527#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14528 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14529#endif
14530 /*
14531 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14532 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14533 */
14534 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14535 AssertRCReturn(rc, rc);
14536 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14537 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14538
14539 if ( pVmxTransient->fIsNestedGuest
14540 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14541 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14542 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14543 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14544 else
14545 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14546 return rc;
14547 }
14548
14549 Assert(CPUMIsGuestInRealModeEx(pCtx));
14550 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14551 Assert(!pVmxTransient->fIsNestedGuest);
14552
14553 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14554 AssertRCReturn(rc, rc);
14555
14556 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14557 if (rcStrict == VINF_SUCCESS)
14558 {
14559 if (!CPUMIsGuestInRealModeEx(pCtx))
14560 {
14561 /*
14562 * The guest is no longer in real-mode, check if we can continue executing the
14563 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14564 */
14565 pVmcsInfo->RealMode.fRealOnV86Active = false;
14566 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14567 {
14568 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14569 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14570 }
14571 else
14572 {
14573 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14574 rcStrict = VINF_EM_RESCHEDULE;
14575 }
14576 }
14577 else
14578 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14579 }
14580 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14581 {
14582 rcStrict = VINF_SUCCESS;
14583 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14584 }
14585 return VBOXSTRICTRC_VAL(rcStrict);
14586}
14587
14588
14589/**
14590 * VM-exit exception handler wrapper for all other exceptions that are not handled
14591 * by a specific handler.
14592 *
14593 * This simply re-injects the exception back into the VM without any special
14594 * processing.
14595 *
14596 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14597 */
14598static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14599{
14600 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14601
14602#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14603 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14604 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14605 ("uVector=%#x u32XcptBitmap=%#X32\n",
14606 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14607 NOREF(pVmcsInfo);
14608#endif
14609
14610 /*
14611 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14612 * would have been handled while checking exits due to event delivery.
14613 */
14614 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14615
14616#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14617 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14618 AssertRCReturn(rc, rc);
14619 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14620#endif
14621
14622#ifdef VBOX_WITH_STATISTICS
14623 switch (uVector)
14624 {
14625 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14626 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14627 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14628 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14629 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14630 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14631 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14632 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14633 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14634 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14635 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14636 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14637 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14638 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14639 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14640 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14641 default:
14642 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14643 break;
14644 }
14645#endif
14646
14647 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14648 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14649 NOREF(uVector);
14650
14651 /* Re-inject the original exception into the guest. */
14652 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14653 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14654 return VINF_SUCCESS;
14655}
14656
14657
14658/**
14659 * VM-exit exception handler for all exceptions (except NMIs!).
14660 *
14661 * @remarks This may be called for both guests and nested-guests. Take care to not
14662 * make assumptions and avoid doing anything that is not relevant when
14663 * executing a nested-guest (e.g., Mesa driver hacks).
14664 */
14665static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14666{
14667 /*
14668 * If this VM-exit occurred while delivering an event through the guest IDT, take
14669 * action based on the return code and additional hints (e.g. for page-faults)
14670 * that will be updated in the VMX transient structure.
14671 */
14672 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14673 if (rcStrict == VINF_SUCCESS)
14674 {
14675 /*
14676 * If an exception caused a VM-exit due to delivery of an event, the original
14677 * event may have to be re-injected into the guest. We shall reinject it and
14678 * continue guest execution. However, page-fault is a complicated case and
14679 * needs additional processing done in hmR0VmxExitXcptPF().
14680 */
14681 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14682 if ( !pVCpu->hm.s.Event.fPending
14683 || uVector == X86_XCPT_PF)
14684 {
14685 switch (uVector)
14686 {
14687 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14688 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14689 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14690 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14691 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14692 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14693 default:
14694 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14695 }
14696 }
14697 }
14698 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14699 {
14700 Assert(pVCpu->hm.s.Event.fPending);
14701 rcStrict = VINF_SUCCESS;
14702 }
14703
14704 return rcStrict;
14705}
14706/** @} */
14707
14708
14709/** @name VM-exit handlers.
14710 * @{
14711 */
14712/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14713/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14714/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14715
14716/**
14717 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14718 */
14719HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14720{
14721 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14722 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14723 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14724 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14725 return VINF_SUCCESS;
14726 return VINF_EM_RAW_INTERRUPT;
14727}
14728
14729
14730/**
14731 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14732 * VM-exit.
14733 */
14734HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14735{
14736 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14737 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14738
14739 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14740 AssertRCReturn(rc, rc);
14741
14742 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14743 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14744 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14745
14746 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14747 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14748 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14749 NOREF(pVmcsInfo);
14750
14751 VBOXSTRICTRC rcStrict;
14752 switch (uExitIntType)
14753 {
14754 /*
14755 * Host physical NMIs:
14756 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14757 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14758 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14759 *
14760 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14761 * See Intel spec. 27.5.5 "Updating Non-Register State".
14762 */
14763 case VMX_EXIT_INT_INFO_TYPE_NMI:
14764 {
14765 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14766 break;
14767 }
14768
14769 /*
14770 * Privileged software exceptions (#DB from ICEBP),
14771 * Software exceptions (#BP and #OF),
14772 * Hardware exceptions:
14773 * Process the required exceptions and resume guest execution if possible.
14774 */
14775 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14776 Assert(uVector == X86_XCPT_DB);
14777 RT_FALL_THRU();
14778 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14779 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14780 RT_FALL_THRU();
14781 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14782 {
14783 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14784 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14785 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14786 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14787 AssertRCReturn(rc, rc);
14788
14789 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14790 break;
14791 }
14792
14793 default:
14794 {
14795 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14796 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14797 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14798 break;
14799 }
14800 }
14801
14802 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14803 return rcStrict;
14804}
14805
14806
14807/**
14808 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14809 */
14810HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14811{
14812 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14813
14814 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14815 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14816 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14817 AssertRCReturn(rc, rc);
14818
14819 /* Evaluate and deliver pending events and resume guest execution. */
14820 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14821 return VINF_SUCCESS;
14822}
14823
14824
14825/**
14826 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14827 */
14828HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14829{
14830 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14831
14832 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14833 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14834 {
14835 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14836 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14837 }
14838
14839 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14840
14841 /*
14842 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14843 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14844 */
14845 uint32_t fIntrState;
14846 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14847 AssertRCReturn(rc, rc);
14848 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14849 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14850 {
14851 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14852 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14853
14854 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14855 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14856 AssertRCReturn(rc, rc);
14857 }
14858
14859 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14860 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14861 AssertRCReturn(rc, rc);
14862
14863 /* Evaluate and deliver pending events and resume guest execution. */
14864 return VINF_SUCCESS;
14865}
14866
14867
14868/**
14869 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14870 */
14871HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14872{
14873 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14874 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14875}
14876
14877
14878/**
14879 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14880 */
14881HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(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 CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14890 */
14891HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14892{
14893 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14894
14895 /*
14896 * Get the state we need and update the exit history entry.
14897 */
14898 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14899 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14900 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14901 AssertRCReturn(rc, rc);
14902
14903 VBOXSTRICTRC rcStrict;
14904 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14905 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14906 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14907 if (!pExitRec)
14908 {
14909 /*
14910 * Regular CPUID instruction execution.
14911 */
14912 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14913 if (rcStrict == VINF_SUCCESS)
14914 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14915 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14916 {
14917 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14918 rcStrict = VINF_SUCCESS;
14919 }
14920 }
14921 else
14922 {
14923 /*
14924 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14925 */
14926 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14927 AssertRCReturn(rc2, rc2);
14928
14929 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14930 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14931
14932 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14934
14935 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14936 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14937 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14938 }
14939 return rcStrict;
14940}
14941
14942
14943/**
14944 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14945 */
14946HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14947{
14948 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14949
14950 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14951 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14952 AssertRCReturn(rc, rc);
14953
14954 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14955 return VINF_EM_RAW_EMULATE_INSTR;
14956
14957 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14958 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14959}
14960
14961
14962/**
14963 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14964 */
14965HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14966{
14967 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14968
14969 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14970 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14971 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14972 AssertRCReturn(rc, rc);
14973
14974 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
14975 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14976 {
14977 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14978 we must reset offsetting on VM-entry. See @bugref{6634}. */
14979 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14980 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14981 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14982 }
14983 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14984 {
14985 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14986 rcStrict = VINF_SUCCESS;
14987 }
14988 return rcStrict;
14989}
14990
14991
14992/**
14993 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14994 */
14995HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14996{
14997 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14998
14999 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15000 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
15001 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15002 AssertRCReturn(rc, rc);
15003
15004 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
15005 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15006 {
15007 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15008 we must reset offsetting on VM-reentry. See @bugref{6634}. */
15009 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15010 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15011 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15012 }
15013 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15014 {
15015 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15016 rcStrict = VINF_SUCCESS;
15017 }
15018 return rcStrict;
15019}
15020
15021
15022/**
15023 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
15024 */
15025HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15026{
15027 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15028
15029 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15030 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
15031 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
15032 AssertRCReturn(rc, rc);
15033
15034 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15035 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
15036 if (RT_LIKELY(rc == VINF_SUCCESS))
15037 {
15038 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15039 Assert(pVmxTransient->cbInstr == 2);
15040 }
15041 else
15042 {
15043 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
15044 rc = VERR_EM_INTERPRETER;
15045 }
15046 return rc;
15047}
15048
15049
15050/**
15051 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
15052 */
15053HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15054{
15055 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15056
15057 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
15058 if (EMAreHypercallInstructionsEnabled(pVCpu))
15059 {
15060 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15061 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
15062 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
15063 AssertRCReturn(rc, rc);
15064
15065 /* Perform the hypercall. */
15066 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
15067 if (rcStrict == VINF_SUCCESS)
15068 {
15069 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15070 AssertRCReturn(rc, rc);
15071 }
15072 else
15073 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15074 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15075 || RT_FAILURE(rcStrict));
15076
15077 /* If the hypercall changes anything other than guest's general-purpose registers,
15078 we would need to reload the guest changed bits here before VM-entry. */
15079 }
15080 else
15081 Log4Func(("Hypercalls not enabled\n"));
15082
15083 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15084 if (RT_FAILURE(rcStrict))
15085 {
15086 hmR0VmxSetPendingXcptUD(pVCpu);
15087 rcStrict = VINF_SUCCESS;
15088 }
15089
15090 return rcStrict;
15091}
15092
15093
15094/**
15095 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15096 */
15097HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15098{
15099 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15100 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15101
15102 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15103 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15104 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15105 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15106 AssertRCReturn(rc, rc);
15107
15108 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15109
15110 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15111 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15112 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15113 {
15114 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15115 rcStrict = VINF_SUCCESS;
15116 }
15117 else
15118 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15119 VBOXSTRICTRC_VAL(rcStrict)));
15120 return rcStrict;
15121}
15122
15123
15124/**
15125 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15126 */
15127HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15128{
15129 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15130
15131 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15132 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15133 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15134 AssertRCReturn(rc, rc);
15135
15136 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15137 if (rcStrict == VINF_SUCCESS)
15138 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15139 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15140 {
15141 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15142 rcStrict = VINF_SUCCESS;
15143 }
15144
15145 return rcStrict;
15146}
15147
15148
15149/**
15150 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15151 */
15152HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15153{
15154 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15155
15156 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15157 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15158 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15159 AssertRCReturn(rc, rc);
15160
15161 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15162 if (RT_SUCCESS(rcStrict))
15163 {
15164 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15165 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15166 rcStrict = VINF_SUCCESS;
15167 }
15168
15169 return rcStrict;
15170}
15171
15172
15173/**
15174 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15175 * VM-exit.
15176 */
15177HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15178{
15179 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15180 return VINF_EM_RESET;
15181}
15182
15183
15184/**
15185 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15186 */
15187HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15188{
15189 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15190
15191 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15192 AssertRCReturn(rc, rc);
15193
15194 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15195 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15196 rc = VINF_SUCCESS;
15197 else
15198 rc = VINF_EM_HALT;
15199
15200 if (rc != VINF_SUCCESS)
15201 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15202 return rc;
15203}
15204
15205
15206/**
15207 * VM-exit handler for instructions that result in a \#UD exception delivered to
15208 * the guest.
15209 */
15210HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15211{
15212 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15213 hmR0VmxSetPendingXcptUD(pVCpu);
15214 return VINF_SUCCESS;
15215}
15216
15217
15218/**
15219 * VM-exit handler for expiry of the VMX-preemption timer.
15220 */
15221HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15222{
15223 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15224
15225 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15226 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15227
15228 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15229 PVM pVM = pVCpu->CTX_SUFF(pVM);
15230 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15231 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15232 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15233}
15234
15235
15236/**
15237 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15238 */
15239HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15240{
15241 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15242
15243 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15244 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15245 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15246 AssertRCReturn(rc, rc);
15247
15248 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15249 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15250 : HM_CHANGED_RAISED_XCPT_MASK);
15251
15252 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15253 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15254
15255 return rcStrict;
15256}
15257
15258
15259/**
15260 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15261 */
15262HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15263{
15264 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15265 /** @todo Use VM-exit instruction information. */
15266 return VERR_EM_INTERPRETER;
15267}
15268
15269
15270/**
15271 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15272 * VM-exit.
15273 */
15274HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15275{
15276 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15277 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15278 AssertRCReturn(rc, rc);
15279
15280 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15281 if (RT_FAILURE(rc))
15282 return rc;
15283
15284 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15285 NOREF(uInvalidReason);
15286
15287#ifdef VBOX_STRICT
15288 uint32_t fIntrState;
15289 RTHCUINTREG uHCReg;
15290 uint64_t u64Val;
15291 uint32_t u32Val;
15292 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15293 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15294 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15295 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15296 AssertRCReturn(rc, rc);
15297
15298 Log4(("uInvalidReason %u\n", uInvalidReason));
15299 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15300 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15301 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15302 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15303
15304 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15305 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15306 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15307 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15308 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15309 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15310 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15311 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15312 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15313 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15314 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15315 {
15316 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15317 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15318 }
15319
15320 hmR0DumpRegs(pVCpu);
15321#endif
15322
15323 return VERR_VMX_INVALID_GUEST_STATE;
15324}
15325
15326/**
15327 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15328 */
15329HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15330{
15331 /*
15332 * Cummulative notes of all recognized but unexpected VM-exits.
15333 *
15334 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15335 * nested-paging is used.
15336 *
15337 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15338 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15339 * this function (and thereby stop VM execution) for handling such instructions.
15340 *
15341 *
15342 * VMX_EXIT_INIT_SIGNAL:
15343 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15344 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15345 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15346 *
15347 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15348 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15349 * See Intel spec. "23.8 Restrictions on VMX operation".
15350 *
15351 * VMX_EXIT_SIPI:
15352 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15353 * activity state is used. We don't make use of it as our guests don't have direct
15354 * access to the host local APIC.
15355 *
15356 * See Intel spec. 25.3 "Other Causes of VM-exits".
15357 *
15358 * VMX_EXIT_IO_SMI:
15359 * VMX_EXIT_SMI:
15360 * This can only happen if we support dual-monitor treatment of SMI, which can be
15361 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15362 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15363 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15364 *
15365 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15366 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15367 *
15368 * VMX_EXIT_ERR_MSR_LOAD:
15369 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15370 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15371 * execution.
15372 *
15373 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15374 *
15375 * VMX_EXIT_ERR_MACHINE_CHECK:
15376 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15377 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15378 * #MC exception abort class exception is raised. We thus cannot assume a
15379 * reasonable chance of continuing any sort of execution and we bail.
15380 *
15381 * See Intel spec. 15.1 "Machine-check Architecture".
15382 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15383 *
15384 * VMX_EXIT_PML_FULL:
15385 * VMX_EXIT_VIRTUALIZED_EOI:
15386 * VMX_EXIT_APIC_WRITE:
15387 * We do not currently support any of these features and thus they are all unexpected
15388 * VM-exits.
15389 *
15390 * VMX_EXIT_GDTR_IDTR_ACCESS:
15391 * VMX_EXIT_LDTR_TR_ACCESS:
15392 * VMX_EXIT_RDRAND:
15393 * VMX_EXIT_RSM:
15394 * VMX_EXIT_VMFUNC:
15395 * VMX_EXIT_ENCLS:
15396 * VMX_EXIT_RDSEED:
15397 * VMX_EXIT_XSAVES:
15398 * VMX_EXIT_XRSTORS:
15399 * VMX_EXIT_UMWAIT:
15400 * VMX_EXIT_TPAUSE:
15401 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15402 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15403 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15404 *
15405 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15406 */
15407 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15408 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15409 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15410}
15411
15412
15413/**
15414 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15415 */
15416HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15417{
15418 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15419
15420 /** @todo Optimize this: We currently drag in in the whole MSR state
15421 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15422 * MSRs required. That would require changes to IEM and possibly CPUM too.
15423 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15424 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15425 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15426 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15427 switch (idMsr)
15428 {
15429 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15430 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15431 }
15432
15433 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15434 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15435 AssertRCReturn(rc, rc);
15436
15437 Log4Func(("ecx=%#RX32\n", idMsr));
15438
15439#ifdef VBOX_STRICT
15440 Assert(!pVmxTransient->fIsNestedGuest);
15441 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15442 {
15443 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15444 && idMsr != MSR_K6_EFER)
15445 {
15446 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15447 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15448 }
15449 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15450 {
15451 Assert(pVmcsInfo->pvMsrBitmap);
15452 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15453 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15454 {
15455 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15456 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15457 }
15458 }
15459 }
15460#endif
15461
15462 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15463 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15464 if (rcStrict == VINF_SUCCESS)
15465 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15466 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15467 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15468 {
15469 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15470 rcStrict = VINF_SUCCESS;
15471 }
15472 else
15473 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15474
15475 return rcStrict;
15476}
15477
15478
15479/**
15480 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15481 */
15482HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15483{
15484 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15485
15486 /** @todo Optimize this: We currently drag in in the whole MSR state
15487 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15488 * MSRs required. That would require changes to IEM and possibly CPUM too.
15489 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15490 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15491 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15492
15493 /*
15494 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15495 * Although we don't need to fetch the base as it will be overwritten shortly, while
15496 * loading guest-state we would also load the entire segment register including limit
15497 * and attributes and thus we need to load them here.
15498 */
15499 switch (idMsr)
15500 {
15501 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15502 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15503 }
15504
15505 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15506 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15507 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15508 AssertRCReturn(rc, rc);
15509
15510 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15511
15512 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15513 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15514
15515 if (rcStrict == VINF_SUCCESS)
15516 {
15517 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15518
15519 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15520 if ( idMsr == MSR_IA32_APICBASE
15521 || ( idMsr >= MSR_IA32_X2APIC_START
15522 && idMsr <= MSR_IA32_X2APIC_END))
15523 {
15524 /*
15525 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15526 * When full APIC register virtualization is implemented we'll have to make
15527 * sure APIC state is saved from the VMCS before IEM changes it.
15528 */
15529 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15530 }
15531 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15532 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15533 else if (idMsr == MSR_K6_EFER)
15534 {
15535 /*
15536 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15537 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15538 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15539 */
15540 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15541 }
15542
15543 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15544 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15545 {
15546 switch (idMsr)
15547 {
15548 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15549 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15550 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15551 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15552 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15553 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15554 default:
15555 {
15556 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15557 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15558 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15559 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15560 break;
15561 }
15562 }
15563 }
15564#ifdef VBOX_STRICT
15565 else
15566 {
15567 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15568 switch (idMsr)
15569 {
15570 case MSR_IA32_SYSENTER_CS:
15571 case MSR_IA32_SYSENTER_EIP:
15572 case MSR_IA32_SYSENTER_ESP:
15573 case MSR_K8_FS_BASE:
15574 case MSR_K8_GS_BASE:
15575 {
15576 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15577 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15578 }
15579
15580 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15581 default:
15582 {
15583 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15584 {
15585 /* EFER MSR writes are always intercepted. */
15586 if (idMsr != MSR_K6_EFER)
15587 {
15588 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15589 idMsr));
15590 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15591 }
15592 }
15593
15594 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15595 {
15596 Assert(pVmcsInfo->pvMsrBitmap);
15597 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15598 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15599 {
15600 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15601 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15602 }
15603 }
15604 break;
15605 }
15606 }
15607 }
15608#endif /* VBOX_STRICT */
15609 }
15610 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15611 {
15612 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15613 rcStrict = VINF_SUCCESS;
15614 }
15615 else
15616 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15617
15618 return rcStrict;
15619}
15620
15621
15622/**
15623 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15624 */
15625HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15626{
15627 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15628
15629 /** @todo The guest has likely hit a contended spinlock. We might want to
15630 * poke a schedule different guest VCPU. */
15631 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15632 if (RT_SUCCESS(rc))
15633 return VINF_EM_RAW_INTERRUPT;
15634
15635 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15636 return rc;
15637}
15638
15639
15640/**
15641 * VM-exit handler for when the TPR value is lowered below the specified
15642 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15643 */
15644HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15645{
15646 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15647 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15648
15649 /*
15650 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15651 * We'll re-evaluate pending interrupts and inject them before the next VM
15652 * entry so we can just continue execution here.
15653 */
15654 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15655 return VINF_SUCCESS;
15656}
15657
15658
15659/**
15660 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15661 * VM-exit.
15662 *
15663 * @retval VINF_SUCCESS when guest execution can continue.
15664 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15665 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15666 * incompatible guest state for VMX execution (real-on-v86 case).
15667 */
15668HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15669{
15670 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15671 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15672
15673 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15674 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15675 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15676 AssertRCReturn(rc, rc);
15677
15678 VBOXSTRICTRC rcStrict;
15679 PVM pVM = pVCpu->CTX_SUFF(pVM);
15680 uint64_t const uExitQual = pVmxTransient->uExitQual;
15681 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15682 switch (uAccessType)
15683 {
15684 /*
15685 * MOV to CRx.
15686 */
15687 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15688 {
15689 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15690 AssertRCReturn(rc, rc);
15691
15692 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15693 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15694 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15695 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15696
15697 /*
15698 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15699 * - When nested paging isn't used.
15700 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15701 * - We are executing in the VM debug loop.
15702 */
15703 Assert( iCrReg != 3
15704 || !pVM->hm.s.fNestedPaging
15705 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15706 || pVCpu->hm.s.fUsingDebugLoop);
15707
15708 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15709 Assert( iCrReg != 8
15710 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15711
15712 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15713 AssertMsg( rcStrict == VINF_SUCCESS
15714 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15715
15716 /*
15717 * This is a kludge for handling switches back to real mode when we try to use
15718 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15719 * deal with special selector values, so we have to return to ring-3 and run
15720 * there till the selector values are V86 mode compatible.
15721 *
15722 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15723 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15724 * this function.
15725 */
15726 if ( iCrReg == 0
15727 && rcStrict == VINF_SUCCESS
15728 && !pVM->hm.s.vmx.fUnrestrictedGuest
15729 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15730 && (uOldCr0 & X86_CR0_PE)
15731 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15732 {
15733 /** @todo Check selectors rather than returning all the time. */
15734 Assert(!pVmxTransient->fIsNestedGuest);
15735 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15736 rcStrict = VINF_EM_RESCHEDULE_REM;
15737 }
15738 break;
15739 }
15740
15741 /*
15742 * MOV from CRx.
15743 */
15744 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15745 {
15746 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15747 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15748
15749 /*
15750 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15751 * - When nested paging isn't used.
15752 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15753 * - We are executing in the VM debug loop.
15754 */
15755 Assert( iCrReg != 3
15756 || !pVM->hm.s.fNestedPaging
15757 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15758 || pVCpu->hm.s.fUsingDebugLoop);
15759
15760 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15761 Assert( iCrReg != 8
15762 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15763
15764 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15765 break;
15766 }
15767
15768 /*
15769 * CLTS (Clear Task-Switch Flag in CR0).
15770 */
15771 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15772 {
15773 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15774 break;
15775 }
15776
15777 /*
15778 * LMSW (Load Machine-Status Word into CR0).
15779 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15780 */
15781 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15782 {
15783 RTGCPTR GCPtrEffDst;
15784 uint8_t const cbInstr = pVmxTransient->cbInstr;
15785 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15786 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15787 if (fMemOperand)
15788 {
15789 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15790 AssertRCReturn(rc, rc);
15791 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15792 }
15793 else
15794 GCPtrEffDst = NIL_RTGCPTR;
15795 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15796 break;
15797 }
15798
15799 default:
15800 {
15801 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15802 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15803 }
15804 }
15805
15806 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15807 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15808 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15809
15810 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15811 NOREF(pVM);
15812 return rcStrict;
15813}
15814
15815
15816/**
15817 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15818 * VM-exit.
15819 */
15820HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15821{
15822 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15823 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15824
15825 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15826 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15827 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15828 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15829 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15830 | CPUMCTX_EXTRN_EFER);
15831 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15832 AssertRCReturn(rc, rc);
15833
15834 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15835 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15836 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15837 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15838 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15839 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15840 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15841 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15842
15843 /*
15844 * Update exit history to see if this exit can be optimized.
15845 */
15846 VBOXSTRICTRC rcStrict;
15847 PCEMEXITREC pExitRec = NULL;
15848 if ( !fGstStepping
15849 && !fDbgStepping)
15850 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15851 !fIOString
15852 ? !fIOWrite
15853 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15854 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15855 : !fIOWrite
15856 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15857 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15858 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15859 if (!pExitRec)
15860 {
15861 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15862 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15863
15864 uint32_t const cbValue = s_aIOSizes[uIOSize];
15865 uint32_t const cbInstr = pVmxTransient->cbInstr;
15866 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15867 PVM pVM = pVCpu->CTX_SUFF(pVM);
15868 if (fIOString)
15869 {
15870 /*
15871 * INS/OUTS - I/O String instruction.
15872 *
15873 * Use instruction-information if available, otherwise fall back on
15874 * interpreting the instruction.
15875 */
15876 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15877 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15878 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15879 if (fInsOutsInfo)
15880 {
15881 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15882 AssertRCReturn(rc2, rc2);
15883 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15884 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15885 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15886 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15887 if (fIOWrite)
15888 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15889 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15890 else
15891 {
15892 /*
15893 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15894 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15895 * See Intel Instruction spec. for "INS".
15896 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15897 */
15898 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15899 }
15900 }
15901 else
15902 rcStrict = IEMExecOne(pVCpu);
15903
15904 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15905 fUpdateRipAlready = true;
15906 }
15907 else
15908 {
15909 /*
15910 * IN/OUT - I/O instruction.
15911 */
15912 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15913 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15914 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15915 if (fIOWrite)
15916 {
15917 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15918 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15919 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15920 && !pCtx->eflags.Bits.u1TF)
15921 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15922 }
15923 else
15924 {
15925 uint32_t u32Result = 0;
15926 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15927 if (IOM_SUCCESS(rcStrict))
15928 {
15929 /* Save result of I/O IN instr. in AL/AX/EAX. */
15930 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15931 }
15932 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15933 && !pCtx->eflags.Bits.u1TF)
15934 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15935 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15936 }
15937 }
15938
15939 if (IOM_SUCCESS(rcStrict))
15940 {
15941 if (!fUpdateRipAlready)
15942 {
15943 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15944 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15945 }
15946
15947 /*
15948 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15949 * while booting Fedora 17 64-bit guest.
15950 *
15951 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15952 */
15953 if (fIOString)
15954 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15955
15956 /*
15957 * If any I/O breakpoints are armed, we need to check if one triggered
15958 * and take appropriate action.
15959 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15960 */
15961 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15962 AssertRCReturn(rc, rc);
15963
15964 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15965 * execution engines about whether hyper BPs and such are pending. */
15966 uint32_t const uDr7 = pCtx->dr[7];
15967 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15968 && X86_DR7_ANY_RW_IO(uDr7)
15969 && (pCtx->cr4 & X86_CR4_DE))
15970 || DBGFBpIsHwIoArmed(pVM)))
15971 {
15972 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15973
15974 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15975 VMMRZCallRing3Disable(pVCpu);
15976 HM_DISABLE_PREEMPT(pVCpu);
15977
15978 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15979
15980 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15981 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15982 {
15983 /* Raise #DB. */
15984 if (fIsGuestDbgActive)
15985 ASMSetDR6(pCtx->dr[6]);
15986 if (pCtx->dr[7] != uDr7)
15987 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15988
15989 hmR0VmxSetPendingXcptDB(pVCpu);
15990 }
15991 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15992 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15993 else if ( rcStrict2 != VINF_SUCCESS
15994 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15995 rcStrict = rcStrict2;
15996 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15997
15998 HM_RESTORE_PREEMPT();
15999 VMMRZCallRing3Enable(pVCpu);
16000 }
16001 }
16002
16003#ifdef VBOX_STRICT
16004 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16005 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
16006 Assert(!fIOWrite);
16007 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16008 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
16009 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
16010 Assert(fIOWrite);
16011 else
16012 {
16013# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
16014 * statuses, that the VMM device and some others may return. See
16015 * IOM_SUCCESS() for guidance. */
16016 AssertMsg( RT_FAILURE(rcStrict)
16017 || rcStrict == VINF_SUCCESS
16018 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
16019 || rcStrict == VINF_EM_DBG_BREAKPOINT
16020 || rcStrict == VINF_EM_RAW_GUEST_TRAP
16021 || rcStrict == VINF_EM_RAW_TO_R3
16022 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16023# endif
16024 }
16025#endif
16026 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
16027 }
16028 else
16029 {
16030 /*
16031 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
16032 */
16033 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16034 AssertRCReturn(rc2, rc2);
16035 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
16036 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
16037 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
16038 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16039 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
16040 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
16041
16042 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16043 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16044
16045 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16046 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16047 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16048 }
16049 return rcStrict;
16050}
16051
16052
16053/**
16054 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16055 * VM-exit.
16056 */
16057HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16058{
16059 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16060
16061 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16062 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16063 AssertRCReturn(rc, rc);
16064 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16065 {
16066 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16067 AssertRCReturn(rc, rc);
16068 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16069 {
16070 uint32_t uErrCode;
16071 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16072 {
16073 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16074 AssertRCReturn(rc, rc);
16075 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16076 }
16077 else
16078 uErrCode = 0;
16079
16080 RTGCUINTPTR GCPtrFaultAddress;
16081 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16082 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16083 else
16084 GCPtrFaultAddress = 0;
16085
16086 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16087 AssertRCReturn(rc, rc);
16088
16089 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16090 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16091
16092 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16093 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16094 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16095 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16096 }
16097 }
16098
16099 /* Fall back to the interpreter to emulate the task-switch. */
16100 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16101 return VERR_EM_INTERPRETER;
16102}
16103
16104
16105/**
16106 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16107 */
16108HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16109{
16110 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16111
16112 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16113 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16114 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16115 AssertRCReturn(rc, rc);
16116 return VINF_EM_DBG_STEPPED;
16117}
16118
16119
16120/**
16121 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16122 */
16123HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16124{
16125 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16126 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16127
16128 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16129 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16130 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16131 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16132 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16133 AssertRCReturn(rc, rc);
16134
16135 /*
16136 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16137 */
16138 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16139 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16140 {
16141 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16142 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16143 {
16144 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16145 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16146 }
16147 }
16148 else
16149 {
16150 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16151 return rcStrict;
16152 }
16153
16154 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16155 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16156 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16157 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16158 AssertRCReturn(rc, rc);
16159
16160 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16161 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16162 switch (uAccessType)
16163 {
16164 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16165 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16166 {
16167 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16168 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16169 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16170
16171 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16172 GCPhys &= PAGE_BASE_GC_MASK;
16173 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16174 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16175 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16176
16177 PVM pVM = pVCpu->CTX_SUFF(pVM);
16178 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16179 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
16180 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16181 CPUMCTX2CORE(pCtx), GCPhys);
16182 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16183 if ( rcStrict == VINF_SUCCESS
16184 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16185 || rcStrict == VERR_PAGE_NOT_PRESENT)
16186 {
16187 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16188 | HM_CHANGED_GUEST_APIC_TPR);
16189 rcStrict = VINF_SUCCESS;
16190 }
16191 break;
16192 }
16193
16194 default:
16195 {
16196 Log4Func(("uAccessType=%#x\n", uAccessType));
16197 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16198 break;
16199 }
16200 }
16201
16202 if (rcStrict != VINF_SUCCESS)
16203 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16204 return rcStrict;
16205}
16206
16207
16208/**
16209 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16210 * VM-exit.
16211 */
16212HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16213{
16214 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16215
16216 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16217 if (pVmxTransient->fWasGuestDebugStateActive)
16218 {
16219 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16220 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16221 }
16222
16223 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16224 if ( !pVCpu->hm.s.fSingleInstruction
16225 && !pVmxTransient->fWasHyperDebugStateActive)
16226 {
16227 Assert(!DBGFIsStepping(pVCpu));
16228 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16229
16230 /* Don't intercept MOV DRx any more. */
16231 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16232 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16233 AssertRCReturn(rc, rc);
16234
16235 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16236 VMMRZCallRing3Disable(pVCpu);
16237 HM_DISABLE_PREEMPT(pVCpu);
16238
16239 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16240 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16241 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16242
16243 HM_RESTORE_PREEMPT();
16244 VMMRZCallRing3Enable(pVCpu);
16245
16246#ifdef VBOX_WITH_STATISTICS
16247 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16248 AssertRCReturn(rc, rc);
16249 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16250 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16251 else
16252 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16253#endif
16254 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16255 return VINF_SUCCESS;
16256 }
16257
16258 /*
16259 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16260 * The EFER MSR is always up-to-date.
16261 * Update the segment registers and DR7 from the CPU.
16262 */
16263 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16264 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16265 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16266 AssertRCReturn(rc, rc);
16267 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16268
16269 PVM pVM = pVCpu->CTX_SUFF(pVM);
16270 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16271 {
16272 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16273 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16274 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16275 if (RT_SUCCESS(rc))
16276 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16277 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16278 }
16279 else
16280 {
16281 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16282 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16283 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16284 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16285 }
16286
16287 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16288 if (RT_SUCCESS(rc))
16289 {
16290 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16291 AssertRCReturn(rc2, rc2);
16292 return VINF_SUCCESS;
16293 }
16294 return rc;
16295}
16296
16297
16298/**
16299 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16300 * Conditional VM-exit.
16301 */
16302HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16303{
16304 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16305 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16306
16307 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16308 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16309 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16310 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16311 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16312 AssertRCReturn(rc, rc);
16313
16314 /*
16315 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16316 */
16317 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16318 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16319 {
16320 /*
16321 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16322 * instruction emulation to inject the original event. Otherwise, injecting the original event
16323 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16324 */
16325 if (!pVCpu->hm.s.Event.fPending)
16326 { /* likely */ }
16327 else
16328 {
16329 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16330#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16331 /** @todo NSTVMX: Think about how this should be handled. */
16332 if (pVmxTransient->fIsNestedGuest)
16333 return VERR_VMX_IPE_3;
16334#endif
16335 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16336 }
16337 }
16338 else
16339 {
16340 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16341 return rcStrict;
16342 }
16343
16344 /*
16345 * Get sufficent state and update the exit history entry.
16346 */
16347 RTGCPHYS GCPhys;
16348 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16349 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16350 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16351 AssertRCReturn(rc, rc);
16352
16353 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16354 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16355 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16356 if (!pExitRec)
16357 {
16358 /*
16359 * If we succeed, resume guest execution.
16360 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16361 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16362 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16363 * weird case. See @bugref{6043}.
16364 */
16365 PVM pVM = pVCpu->CTX_SUFF(pVM);
16366 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16367 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16368 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16369 if ( rcStrict == VINF_SUCCESS
16370 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16371 || rcStrict == VERR_PAGE_NOT_PRESENT)
16372 {
16373 /* Successfully handled MMIO operation. */
16374 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16375 | HM_CHANGED_GUEST_APIC_TPR);
16376 rcStrict = VINF_SUCCESS;
16377 }
16378 }
16379 else
16380 {
16381 /*
16382 * Frequent exit or something needing probing. Call EMHistoryExec.
16383 */
16384 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16385 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16386
16387 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16388 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16389
16390 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16391 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16392 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16393 }
16394 return rcStrict;
16395}
16396
16397
16398/**
16399 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16400 * VM-exit.
16401 */
16402HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16403{
16404 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16405 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16406
16407 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16408 rc |= hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16409 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16410 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16411 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16412 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16413 AssertRCReturn(rc, rc);
16414
16415 /*
16416 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16417 */
16418 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16419 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16420 {
16421 /*
16422 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16423 * we shall resolve the nested #PF and re-inject the original event.
16424 */
16425 if (pVCpu->hm.s.Event.fPending)
16426 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16427 }
16428 else
16429 {
16430 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16431 return rcStrict;
16432 }
16433
16434 RTGCPHYS GCPhys;
16435 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16436 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16437 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16438 AssertRCReturn(rc, rc);
16439
16440 uint64_t const uExitQual = pVmxTransient->uExitQual;
16441 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
16442
16443 RTGCUINT uErrorCode = 0;
16444 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16445 uErrorCode |= X86_TRAP_PF_ID;
16446 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16447 uErrorCode |= X86_TRAP_PF_RW;
16448 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16449 uErrorCode |= X86_TRAP_PF_P;
16450
16451 PVM pVM = pVCpu->CTX_SUFF(pVM);
16452 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16453 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
16454
16455 /*
16456 * Handle the pagefault trap for the nested shadow table.
16457 */
16458 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16459 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16460 TRPMResetTrap(pVCpu);
16461
16462 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16463 if ( rcStrict == VINF_SUCCESS
16464 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16465 || rcStrict == VERR_PAGE_NOT_PRESENT)
16466 {
16467 /* Successfully synced our nested page tables. */
16468 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16469 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16470 return VINF_SUCCESS;
16471 }
16472
16473 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16474 return rcStrict;
16475}
16476
16477
16478#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16479/**
16480 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16481 */
16482HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16483{
16484 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16485
16486 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16487 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16488 | CPUMCTX_EXTRN_HWVIRT
16489 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16490 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16491 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16492 AssertRCReturn(rc, rc);
16493
16494 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16495
16496 VMXVEXITINFO ExitInfo;
16497 RT_ZERO(ExitInfo);
16498 ExitInfo.uReason = pVmxTransient->uExitReason;
16499 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16500 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16501 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16502 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16503
16504 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16505 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16506 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16507 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16508 {
16509 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16510 rcStrict = VINF_SUCCESS;
16511 }
16512 return rcStrict;
16513}
16514
16515
16516/**
16517 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16518 */
16519HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16520{
16521 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16522
16523 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16524 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16525 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16526 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16527 AssertRCReturn(rc, rc);
16528
16529 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16530
16531 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16532 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16533 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16534 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16535 {
16536 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16537 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16538 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16539 }
16540 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16541 return rcStrict;
16542}
16543
16544
16545/**
16546 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16547 */
16548HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16549{
16550 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16551
16552 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16553 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16554 | CPUMCTX_EXTRN_HWVIRT
16555 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16556 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16557 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16558 AssertRCReturn(rc, rc);
16559
16560 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16561
16562 VMXVEXITINFO ExitInfo;
16563 RT_ZERO(ExitInfo);
16564 ExitInfo.uReason = pVmxTransient->uExitReason;
16565 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16566 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16567 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16568 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16569
16570 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16571 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16572 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16573 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16574 {
16575 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16576 rcStrict = VINF_SUCCESS;
16577 }
16578 return rcStrict;
16579}
16580
16581
16582/**
16583 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16584 */
16585HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16586{
16587 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16588
16589 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16590 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16591 | CPUMCTX_EXTRN_HWVIRT
16592 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16593 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16594 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16595 AssertRCReturn(rc, rc);
16596
16597 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16598
16599 VMXVEXITINFO ExitInfo;
16600 RT_ZERO(ExitInfo);
16601 ExitInfo.uReason = pVmxTransient->uExitReason;
16602 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16603 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16604 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16605 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16606
16607 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16608 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16609 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16610 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16611 {
16612 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16613 rcStrict = VINF_SUCCESS;
16614 }
16615 return rcStrict;
16616}
16617
16618
16619/**
16620 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16621 */
16622HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16623{
16624 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16625
16626 /*
16627 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16628 * thus might not need to import the shadow VMCS state, it's safer just in case
16629 * code elsewhere dares look at unsynced VMCS fields.
16630 */
16631 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16632 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16633 | CPUMCTX_EXTRN_HWVIRT
16634 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16635 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16636 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16637 AssertRCReturn(rc, rc);
16638
16639 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16640
16641 VMXVEXITINFO ExitInfo;
16642 RT_ZERO(ExitInfo);
16643 ExitInfo.uReason = pVmxTransient->uExitReason;
16644 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16645 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16646 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16647 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16648 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16649
16650 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16651 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16652 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16653 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16654 {
16655 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16656 rcStrict = VINF_SUCCESS;
16657 }
16658 return rcStrict;
16659}
16660
16661
16662/**
16663 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16664 */
16665HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16666{
16667 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16668
16669 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16670 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16671 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16672 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16673 AssertRCReturn(rc, rc);
16674
16675 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16676
16677 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16678 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16679 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16680 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16681 {
16682 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16683 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16684 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16685 }
16686 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16687 return rcStrict;
16688}
16689
16690
16691/**
16692 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16693 */
16694HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16695{
16696 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16697
16698 /*
16699 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16700 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16701 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16702 */
16703 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16704 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16705 | CPUMCTX_EXTRN_HWVIRT
16706 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16707 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16708 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16709 AssertRCReturn(rc, rc);
16710
16711 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16712
16713 VMXVEXITINFO ExitInfo;
16714 RT_ZERO(ExitInfo);
16715 ExitInfo.uReason = pVmxTransient->uExitReason;
16716 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16717 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16718 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16719 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16720 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16721
16722 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16723 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16724 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16725 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16726 {
16727 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16728 rcStrict = VINF_SUCCESS;
16729 }
16730 return rcStrict;
16731}
16732
16733
16734/**
16735 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16736 */
16737HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16738{
16739 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16740
16741 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16742 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16743 | CPUMCTX_EXTRN_HWVIRT
16744 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16745 AssertRCReturn(rc, rc);
16746
16747 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16748
16749 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16750 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16751 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16752 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16753 {
16754 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16755 rcStrict = VINF_SUCCESS;
16756 }
16757 return rcStrict;
16758}
16759
16760
16761/**
16762 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16763 */
16764HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16765{
16766 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16767
16768 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16769 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16770 | CPUMCTX_EXTRN_HWVIRT
16771 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16772 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16773 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16774 AssertRCReturn(rc, rc);
16775
16776 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16777
16778 VMXVEXITINFO ExitInfo;
16779 RT_ZERO(ExitInfo);
16780 ExitInfo.uReason = pVmxTransient->uExitReason;
16781 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16782 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16783 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16784 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16785
16786 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16787 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16788 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16789 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16790 {
16791 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16792 rcStrict = VINF_SUCCESS;
16793 }
16794 return rcStrict;
16795}
16796
16797
16798/**
16799 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16800 */
16801HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16802{
16803 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16804
16805 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16806 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16807 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16808 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16809 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16810 AssertRCReturn(rc, rc);
16811
16812 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16813
16814 VMXVEXITINFO ExitInfo;
16815 RT_ZERO(ExitInfo);
16816 ExitInfo.uReason = pVmxTransient->uExitReason;
16817 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16818 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16819 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16820 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16821
16822 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16823 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16824 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16825 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16826 {
16827 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16828 rcStrict = VINF_SUCCESS;
16829 }
16830 return rcStrict;
16831}
16832#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16833/** @} */
16834
16835
16836#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16837/** @name Nested-guest VM-exit handlers.
16838 * @{
16839 */
16840/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16841/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16842/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16843
16844/**
16845 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16846 * Conditional VM-exit.
16847 */
16848HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16849{
16850 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16851
16852 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16853 AssertRCReturn(rc, rc);
16854
16855 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16856 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16857 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16858
16859 switch (uExitIntType)
16860 {
16861 /*
16862 * Physical NMIs:
16863 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16864 */
16865 case VMX_EXIT_INT_INFO_TYPE_NMI:
16866 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16867
16868 /*
16869 * Hardware exceptions,
16870 * Software exceptions,
16871 * Privileged software exceptions:
16872 * Figure out if the exception must be delivered to the guest or the nested-guest.
16873 */
16874 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16875 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16876 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16877 {
16878 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16879 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16880 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16881 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16882 AssertRCReturn(rc, rc);
16883
16884 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16885 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16886 pVmxTransient->uExitIntErrorCode);
16887 if (fIntercept)
16888 {
16889 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16890 AssertRCReturn(rc, rc);
16891
16892 /*
16893 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16894 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16895 * length. However, if delivery of a software interrupt, software exception or privileged
16896 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16897 */
16898 VMXVEXITINFO ExitInfo;
16899 RT_ZERO(ExitInfo);
16900 ExitInfo.uReason = pVmxTransient->uExitReason;
16901 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16902 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16903
16904 VMXVEXITEVENTINFO ExitEventInfo;
16905 RT_ZERO(ExitEventInfo);
16906 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16907 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16908 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16909 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16910 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16911 }
16912
16913 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs. */
16914 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16915 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16916 }
16917
16918 /*
16919 * Software interrupts:
16920 * VM-exits cannot be caused by software interrupts.
16921 *
16922 * External interrupts:
16923 * This should only happen when "acknowledge external interrupts on VM-exit"
16924 * control is set. However, we never set this when executing a guest or
16925 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16926 * the guest.
16927 */
16928 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16929 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16930 default:
16931 {
16932 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16933 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16934 }
16935 }
16936}
16937
16938
16939/**
16940 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16941 * Unconditional VM-exit.
16942 */
16943HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16944{
16945 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16946 return IEMExecVmxVmexitTripleFault(pVCpu);
16947}
16948
16949
16950/**
16951 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16952 */
16953HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16954{
16955 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16956
16957 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16958 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16959 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16960}
16961
16962
16963/**
16964 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16965 */
16966HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16967{
16968 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16969
16970 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16971 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16972 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16973}
16974
16975
16976/**
16977 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16978 * Unconditional VM-exit.
16979 */
16980HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16981{
16982 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16983
16984 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16985 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16986 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16987 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16988 AssertRCReturn(rc, rc);
16989
16990 VMXVEXITINFO ExitInfo;
16991 RT_ZERO(ExitInfo);
16992 ExitInfo.uReason = pVmxTransient->uExitReason;
16993 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16994 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16995
16996 VMXVEXITEVENTINFO ExitEventInfo;
16997 RT_ZERO(ExitEventInfo);
16998 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16999 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17000 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
17001}
17002
17003
17004/**
17005 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
17006 */
17007HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17008{
17009 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17010
17011 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
17012 {
17013 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17014 AssertRCReturn(rc, rc);
17015 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17016 }
17017 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
17018}
17019
17020
17021/**
17022 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
17023 */
17024HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17025{
17026 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17027
17028 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17029 {
17030 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17031 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17032 AssertRCReturn(rc, rc);
17033
17034 VMXVEXITINFO ExitInfo;
17035 RT_ZERO(ExitInfo);
17036 ExitInfo.uReason = pVmxTransient->uExitReason;
17037 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17038 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17039 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17040 }
17041 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17042}
17043
17044
17045/**
17046 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17047 */
17048HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17049{
17050 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17051
17052 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17053 {
17054 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17055 AssertRCReturn(rc, rc);
17056 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17057 }
17058 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17059}
17060
17061
17062/**
17063 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17064 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17065 */
17066HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17067{
17068 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17069
17070 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17071 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17072
17073 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17074 AssertRCReturn(rc, rc);
17075
17076 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17077 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17078 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17079
17080 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17081 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17082 u64VmcsField &= UINT64_C(0xffffffff);
17083
17084 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17085 {
17086 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17087 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17088 AssertRCReturn(rc, rc);
17089
17090 VMXVEXITINFO ExitInfo;
17091 RT_ZERO(ExitInfo);
17092 ExitInfo.uReason = pVmxTransient->uExitReason;
17093 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17094 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17095 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17096 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17097 }
17098
17099 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17100 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17101 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17102}
17103
17104
17105/**
17106 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17107 */
17108HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17109{
17110 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17111
17112 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17113 {
17114 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17115 AssertRCReturn(rc, rc);
17116 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17117 }
17118
17119 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17120}
17121
17122
17123/**
17124 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17125 * Conditional VM-exit.
17126 */
17127HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17128{
17129 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17130
17131 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17132 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17133 AssertRCReturn(rc, rc);
17134
17135 VBOXSTRICTRC rcStrict;
17136 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17137 switch (uAccessType)
17138 {
17139 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17140 {
17141 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17142 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17143 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17144 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17145
17146 bool fIntercept;
17147 switch (iCrReg)
17148 {
17149 case 0:
17150 case 4:
17151 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17152 break;
17153
17154 case 3:
17155 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17156 break;
17157
17158 case 8:
17159 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17160 break;
17161
17162 default:
17163 fIntercept = false;
17164 break;
17165 }
17166 if (fIntercept)
17167 {
17168 VMXVEXITINFO ExitInfo;
17169 RT_ZERO(ExitInfo);
17170 ExitInfo.uReason = pVmxTransient->uExitReason;
17171 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17172 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17173 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17174 }
17175 else
17176 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17177 break;
17178 }
17179
17180 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17181 {
17182 /*
17183 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17184 * CR2 reads do not cause a VM-exit.
17185 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17186 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17187 */
17188 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17189 if ( iCrReg == 3
17190 || iCrReg == 8)
17191 {
17192 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17193 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17194 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17195 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17196 {
17197 VMXVEXITINFO ExitInfo;
17198 RT_ZERO(ExitInfo);
17199 ExitInfo.uReason = pVmxTransient->uExitReason;
17200 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17201 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17202 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17203 }
17204 else
17205 {
17206 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17207 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17208 }
17209 }
17210 else
17211 {
17212 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17213 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17214 }
17215 break;
17216 }
17217
17218 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17219 {
17220 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17221 Assert(pVmcsNstGst);
17222 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17223 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17224 if ( (uGstHostMask & X86_CR0_TS)
17225 && (uReadShadow & X86_CR0_TS))
17226 {
17227 VMXVEXITINFO ExitInfo;
17228 RT_ZERO(ExitInfo);
17229 ExitInfo.uReason = pVmxTransient->uExitReason;
17230 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17231 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17232 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17233 }
17234 else
17235 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17236 break;
17237 }
17238
17239 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17240 {
17241 RTGCPTR GCPtrEffDst;
17242 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17243 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17244 if (fMemOperand)
17245 {
17246 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17247 AssertRCReturn(rc, rc);
17248 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17249 }
17250 else
17251 GCPtrEffDst = NIL_RTGCPTR;
17252
17253 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17254 {
17255 VMXVEXITINFO ExitInfo;
17256 RT_ZERO(ExitInfo);
17257 ExitInfo.uReason = pVmxTransient->uExitReason;
17258 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17259 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17260 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17261 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17262 }
17263 else
17264 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17265 break;
17266 }
17267
17268 default:
17269 {
17270 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17271 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17272 }
17273 }
17274
17275 if (rcStrict == VINF_IEM_RAISED_XCPT)
17276 {
17277 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17278 rcStrict = VINF_SUCCESS;
17279 }
17280 return rcStrict;
17281}
17282
17283
17284/**
17285 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17286 * Conditional VM-exit.
17287 */
17288HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17289{
17290 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17291
17292 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17293 {
17294 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17295 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17296 AssertRCReturn(rc, rc);
17297
17298 VMXVEXITINFO ExitInfo;
17299 RT_ZERO(ExitInfo);
17300 ExitInfo.uReason = pVmxTransient->uExitReason;
17301 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17302 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17303 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17304 }
17305 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17306}
17307
17308
17309/**
17310 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17311 * Conditional VM-exit.
17312 */
17313HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17314{
17315 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17316
17317 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17318 AssertRCReturn(rc, rc);
17319
17320 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17321 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17322 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17323
17324 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17325 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17326 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17327 {
17328 /*
17329 * IN/OUT instruction:
17330 * - Provides VM-exit instruction length.
17331 *
17332 * INS/OUTS instruction:
17333 * - Provides VM-exit instruction length.
17334 * - Provides Guest-linear address.
17335 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17336 */
17337 PVM pVM = pVCpu->CTX_SUFF(pVM);
17338 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17339 AssertRCReturn(rc, rc);
17340
17341 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17342 pVmxTransient->ExitInstrInfo.u = 0;
17343 pVmxTransient->uGuestLinearAddr = 0;
17344
17345 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17346 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17347 if (fIOString)
17348 {
17349 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17350 if (fVmxInsOutsInfo)
17351 {
17352 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17353 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17354 }
17355 }
17356 AssertRCReturn(rc, rc);
17357
17358 VMXVEXITINFO ExitInfo;
17359 RT_ZERO(ExitInfo);
17360 ExitInfo.uReason = pVmxTransient->uExitReason;
17361 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17362 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17363 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17364 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17365 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17366 }
17367 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17368}
17369
17370
17371/**
17372 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17373 */
17374HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17375{
17376 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17377
17378 uint32_t fMsrpm;
17379 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17380 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17381 else
17382 fMsrpm = VMXMSRPM_EXIT_RD;
17383
17384 if (fMsrpm & VMXMSRPM_EXIT_RD)
17385 {
17386 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17387 AssertRCReturn(rc, rc);
17388 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17389 }
17390 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17391}
17392
17393
17394/**
17395 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17396 */
17397HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17398{
17399 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17400
17401 uint32_t fMsrpm;
17402 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17403 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17404 else
17405 fMsrpm = VMXMSRPM_EXIT_WR;
17406
17407 if (fMsrpm & VMXMSRPM_EXIT_WR)
17408 {
17409 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17410 AssertRCReturn(rc, rc);
17411 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17412 }
17413 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17414}
17415
17416
17417/**
17418 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17419 */
17420HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17421{
17422 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17423
17424 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17425 {
17426 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17427 AssertRCReturn(rc, rc);
17428 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17429 }
17430 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17431}
17432
17433
17434/**
17435 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17436 * VM-exit.
17437 */
17438HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17439{
17440 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17441
17442 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17443 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17444}
17445
17446
17447/**
17448 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17449 */
17450HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17451{
17452 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17453
17454 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17455 {
17456 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17457 AssertRCReturn(rc, rc);
17458 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17459 }
17460 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17461}
17462
17463
17464/**
17465 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17466 */
17467HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17468{
17469 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17470
17471 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17472 * PAUSE when executing a nested-guest? If it does not, we would not need
17473 * to check for the intercepts here. Just call VM-exit... */
17474
17475 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17476 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17477 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17478 {
17479 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17480 AssertRCReturn(rc, rc);
17481 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17482 }
17483 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17484}
17485
17486
17487/**
17488 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17489 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17490 */
17491HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17492{
17493 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17494
17495 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17496 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17497 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17498}
17499
17500
17501/**
17502 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17503 * VM-exit.
17504 */
17505HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17506{
17507 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17508
17509 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
17510 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
17511 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17512 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17513 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17514 AssertRCReturn(rc, rc);
17515
17516 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17517 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17518 AssertRCReturn(rc, rc);
17519
17520 VMXVEXITINFO ExitInfo;
17521 RT_ZERO(ExitInfo);
17522 ExitInfo.uReason = pVmxTransient->uExitReason;
17523 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17524 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17525
17526 VMXVEXITEVENTINFO ExitEventInfo;
17527 RT_ZERO(ExitEventInfo);
17528 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17529 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17530 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17531}
17532
17533
17534/**
17535 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17536 * Conditional VM-exit.
17537 */
17538HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17539{
17540 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17541
17542 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17543 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17544 AssertRCReturn(rc, rc);
17545
17546 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17547}
17548
17549
17550/**
17551 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17552 * Conditional VM-exit.
17553 */
17554HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17555{
17556 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17557
17558 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17559 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17560 AssertRCReturn(rc, rc);
17561
17562 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17563}
17564
17565
17566/**
17567 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17568 */
17569HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17570{
17571 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17572
17573 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17574 {
17575 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17576 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17577 AssertRCReturn(rc, rc);
17578 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17579 }
17580 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17581}
17582
17583
17584/**
17585 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17586 */
17587HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17588{
17589 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17590
17591 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17592 {
17593 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17594 AssertRCReturn(rc, rc);
17595 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17596 }
17597 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17598}
17599
17600
17601/**
17602 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17603 */
17604HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17605{
17606 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17607
17608 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17609 {
17610 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17611 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17612 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17613 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17614 AssertRCReturn(rc, rc);
17615
17616 VMXVEXITINFO ExitInfo;
17617 RT_ZERO(ExitInfo);
17618 ExitInfo.uReason = pVmxTransient->uExitReason;
17619 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17620 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17621 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17622 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17623 }
17624 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17625}
17626
17627
17628/**
17629 * Nested-guest VM-exit handler for invalid-guest state
17630 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17631 */
17632HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17633{
17634 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17635
17636 /*
17637 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17638 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17639 * Handle it like it's in an invalid guest state of the outer guest.
17640 *
17641 * When the fast path is implemented, this should be changed to cause the corresponding
17642 * nested-guest VM-exit.
17643 */
17644 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17645}
17646
17647
17648/**
17649 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17650 * and only provide the instruction length.
17651 *
17652 * Unconditional VM-exit.
17653 */
17654HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17655{
17656 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17657
17658#ifdef VBOX_STRICT
17659 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17660 switch (pVmxTransient->uExitReason)
17661 {
17662 case VMX_EXIT_ENCLS:
17663 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17664 break;
17665
17666 case VMX_EXIT_VMFUNC:
17667 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17668 break;
17669 }
17670#endif
17671
17672 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17673 AssertRCReturn(rc, rc);
17674 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17675}
17676
17677
17678/**
17679 * Nested-guest VM-exit handler for instructions that provide instruction length as
17680 * well as more information.
17681 *
17682 * Unconditional VM-exit.
17683 */
17684HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17685{
17686 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17687
17688#ifdef VBOX_STRICT
17689 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17690 switch (pVmxTransient->uExitReason)
17691 {
17692 case VMX_EXIT_GDTR_IDTR_ACCESS:
17693 case VMX_EXIT_LDTR_TR_ACCESS:
17694 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17695 break;
17696
17697 case VMX_EXIT_RDRAND:
17698 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17699 break;
17700
17701 case VMX_EXIT_RDSEED:
17702 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17703 break;
17704
17705 case VMX_EXIT_XSAVES:
17706 case VMX_EXIT_XRSTORS:
17707 /** @todo NSTVMX: Verify XSS-bitmap. */
17708 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17709 break;
17710
17711 case VMX_EXIT_UMWAIT:
17712 case VMX_EXIT_TPAUSE:
17713 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17714 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17715 break;
17716 }
17717#endif
17718
17719 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17720 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17721 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17722 AssertRCReturn(rc, rc);
17723
17724 VMXVEXITINFO ExitInfo;
17725 RT_ZERO(ExitInfo);
17726 ExitInfo.uReason = pVmxTransient->uExitReason;
17727 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17728 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17729 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17730 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17731}
17732
17733/** @} */
17734#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17735
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