VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Use CPUM[Is|Set]GuestVmxInterceptEvents. Added comment regarding TRPM and intercepting events in the nested-guest.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 708.2 KB
Line 
1/* $Id: HMVMXR0.cpp 80810 2019-09-16 06:38:37Z 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/tm.h>
35#include <VBox/vmm/em.h>
36#include <VBox/vmm/gim.h>
37#include <VBox/vmm/apic.h>
38#ifdef VBOX_WITH_REM
39# include <VBox/vmm/rem.h>
40#endif
41#include "HMInternal.h"
42#include <VBox/vmm/vmcc.h>
43#include <VBox/vmm/hmvmxinline.h>
44#include "HMVMXR0.h"
45#include "dtrace/VBoxVMM.h"
46
47#ifdef DEBUG_ramshankar
48# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
49# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
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#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
86#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
87
88/** All the VMCS fields required for processing of exception/NMI VM-exits. */
89#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
90 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
91 | HMVMX_READ_EXIT_INSTR_LEN \
92 | HMVMX_READ_IDT_VECTORING_INFO \
93 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
94
95/** Assert that all the given fields have been read from the VMCS. */
96#ifdef VBOX_STRICT
97# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
98 do { \
99 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
100 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
101 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
102 } while (0)
103#else
104# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
105#endif
106
107/**
108 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
109 * guest using hardware-assisted VMX.
110 *
111 * This excludes state like GPRs (other than RSP) which are always are
112 * swapped and restored across the world-switch and also registers like EFER,
113 * MSR which cannot be modified by the guest without causing a VM-exit.
114 */
115#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
116 | CPUMCTX_EXTRN_RFLAGS \
117 | CPUMCTX_EXTRN_RSP \
118 | CPUMCTX_EXTRN_SREG_MASK \
119 | CPUMCTX_EXTRN_TABLE_MASK \
120 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
121 | CPUMCTX_EXTRN_SYSCALL_MSRS \
122 | CPUMCTX_EXTRN_SYSENTER_MSRS \
123 | CPUMCTX_EXTRN_TSC_AUX \
124 | CPUMCTX_EXTRN_OTHER_MSRS \
125 | CPUMCTX_EXTRN_CR0 \
126 | CPUMCTX_EXTRN_CR3 \
127 | CPUMCTX_EXTRN_CR4 \
128 | CPUMCTX_EXTRN_DR7 \
129 | CPUMCTX_EXTRN_HWVIRT \
130 | CPUMCTX_EXTRN_HM_VMX_MASK)
131
132/**
133 * Exception bitmap mask for real-mode guests (real-on-v86).
134 *
135 * We need to intercept all exceptions manually except:
136 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
137 * due to bugs in Intel CPUs.
138 * - \#PF need not be intercepted even in real-mode if we have nested paging
139 * support.
140 */
141#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
142 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
143 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
144 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
145 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
146 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
147 | RT_BIT(X86_XCPT_XF))
148
149/** Maximum VM-instruction error number. */
150#define HMVMX_INSTR_ERROR_MAX 28
151
152/** Profiling macro. */
153#ifdef HM_PROFILE_EXIT_DISPATCH
154# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
155# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
156#else
157# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
158# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
159#endif
160
161/** Assert that preemption is disabled or covered by thread-context hooks. */
162#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
163 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
164
165/** Assert that we haven't migrated CPUs when thread-context hooks are not
166 * used. */
167#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
168 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
169 ("Illegal migration! Entered on CPU %u Current %u\n", \
170 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
171
172/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
173 * context. */
174#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
175 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
176 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
177
178/** Log the VM-exit reason with an easily visible marker to identify it in a
179 * potential sea of logging data. */
180#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
181 do { \
182 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
183 HMGetVmxExitName(a_uExitReason))); \
184 } while (0) \
185
186
187/*********************************************************************************************************************************
188* Structures and Typedefs *
189*********************************************************************************************************************************/
190/**
191 * VMX per-VCPU transient state.
192 *
193 * A state structure for holding miscellaneous information across
194 * VMX non-root operation and restored after the transition.
195 */
196typedef struct VMXTRANSIENT
197{
198 /** The host's rflags/eflags. */
199 RTCCUINTREG fEFlags;
200
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 /** The Guest-physical address. */
217 uint64_t uGuestPhysicalAddr;
218 /** The Guest pending-debug exceptions. */
219 uint64_t uGuestPendingDbgXcpts;
220
221 /** The VM-exit interruption-information field. */
222 uint32_t uExitIntInfo;
223 /** The VM-exit instruction-length field. */
224 uint32_t cbExitInstr;
225 /** The VM-exit instruction-information field. */
226 VMXEXITINSTRINFO ExitInstrInfo;
227 /** Whether the VM-entry failed or not. */
228 bool fVMEntryFailed;
229 /** Whether we are currently executing a nested-guest. */
230 bool fIsNestedGuest;
231 /** Alignment. */
232 uint8_t abAlignment1[2];
233
234 /** The VM-entry interruption-information field. */
235 uint32_t uEntryIntInfo;
236 /** The VM-entry exception error code field. */
237 uint32_t uEntryXcptErrorCode;
238 /** The VM-entry instruction length field. */
239 uint32_t cbEntryInstr;
240
241 /** IDT-vectoring information field. */
242 uint32_t uIdtVectoringInfo;
243 /** IDT-vectoring error code. */
244 uint32_t uIdtVectoringErrorCode;
245
246 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
247 uint32_t fVmcsFieldsRead;
248
249 /** Whether the guest debug state was active at the time of VM-exit. */
250 bool fWasGuestDebugStateActive;
251 /** Whether the hyper debug state was active at the time of VM-exit. */
252 bool fWasHyperDebugStateActive;
253 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
254 bool fUpdatedTscOffsettingAndPreemptTimer;
255 /** Whether the VM-exit was caused by a page-fault during delivery of a
256 * contributory exception or a page-fault. */
257 bool fVectoringDoublePF;
258 /** Whether the VM-exit was caused by a page-fault during delivery of an
259 * external interrupt or NMI. */
260 bool fVectoringPF;
261 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
262 * area after VM-exit. */
263 bool fRemoveTscAuxMsr;
264 bool afAlignment0[2];
265
266 /** The VMCS info. object. */
267 PVMXVMCSINFO pVmcsInfo;
268} VMXTRANSIENT;
269AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
271AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
272AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
273AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
274AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
275/** Pointer to VMX transient state. */
276typedef VMXTRANSIENT *PVMXTRANSIENT;
277/** Pointer to a const VMX transient state. */
278typedef const VMXTRANSIENT *PCVMXTRANSIENT;
279
280/**
281 * Memory operand read or write access.
282 */
283typedef enum VMXMEMACCESS
284{
285 VMXMEMACCESS_READ = 0,
286 VMXMEMACCESS_WRITE = 1
287} VMXMEMACCESS;
288
289/**
290 * VMX VM-exit handler.
291 *
292 * @returns Strict VBox status code (i.e. informational status codes too).
293 * @param pVCpu The cross context virtual CPU structure.
294 * @param pVmxTransient The VMX-transient structure.
295 */
296#ifndef HMVMX_USE_FUNCTION_TABLE
297typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
298#else
299typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
300/** Pointer to VM-exit handler. */
301typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
302#endif
303
304/**
305 * VMX VM-exit handler, non-strict status code.
306 *
307 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
308 *
309 * @returns VBox status code, no informational status code returned.
310 * @param pVCpu The cross context virtual CPU structure.
311 * @param pVmxTransient The VMX-transient structure.
312 *
313 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
314 * use of that status code will be replaced with VINF_EM_SOMETHING
315 * later when switching over to IEM.
316 */
317#ifndef HMVMX_USE_FUNCTION_TABLE
318typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
319#else
320typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
321#endif
322
323
324/*********************************************************************************************************************************
325* Internal Functions *
326*********************************************************************************************************************************/
327#ifndef HMVMX_USE_FUNCTION_TABLE
328DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
329# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
330# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
331#else
332# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
333# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
334#endif
335#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
336DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
337#endif
338
339static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
340
341/** @name VM-exit handler prototypes.
342 * @{
343 */
344static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
345static FNVMXEXITHANDLER hmR0VmxExitExtInt;
346static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
347static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
348static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
349static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
350static FNVMXEXITHANDLER hmR0VmxExitCpuid;
351static FNVMXEXITHANDLER hmR0VmxExitGetsec;
352static FNVMXEXITHANDLER hmR0VmxExitHlt;
353static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
354static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
355static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
356static FNVMXEXITHANDLER hmR0VmxExitVmcall;
357#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
358static FNVMXEXITHANDLER hmR0VmxExitVmclear;
359static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
360static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
361static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
362static FNVMXEXITHANDLER hmR0VmxExitVmread;
363static FNVMXEXITHANDLER hmR0VmxExitVmresume;
364static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
365static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
366static FNVMXEXITHANDLER hmR0VmxExitVmxon;
367static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
368#endif
369static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
370static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
371static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
372static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
373static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
374static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
375static FNVMXEXITHANDLER hmR0VmxExitMwait;
376static FNVMXEXITHANDLER hmR0VmxExitMtf;
377static FNVMXEXITHANDLER hmR0VmxExitMonitor;
378static FNVMXEXITHANDLER hmR0VmxExitPause;
379static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
380static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
381static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
382static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
383static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
384static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
385static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
386static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
387static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
389static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
390static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
391/** @} */
392
393#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
394/** @name Nested-guest VM-exit handler prototypes.
395 * @{
396 */
397static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
398static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
399static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
400static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
401static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
402static FNVMXEXITHANDLER hmR0VmxExitHltNested;
403static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
404static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
405static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
406static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
407static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
408static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
409static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
410static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
411static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
412static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
413static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
414static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
415static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
416static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
417static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
418static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
419static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
420static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
421static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
422static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
423static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
424static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
425static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
426/** @} */
427#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
428
429
430/*********************************************************************************************************************************
431* Global Variables *
432*********************************************************************************************************************************/
433#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
434/**
435 * Array of all VMCS fields.
436 * Any fields added to the VT-x spec. should be added here.
437 *
438 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
439 * of nested-guests.
440 */
441static const uint32_t g_aVmcsFields[] =
442{
443 /* 16-bit control fields. */
444 VMX_VMCS16_VPID,
445 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
446 VMX_VMCS16_EPTP_INDEX,
447
448 /* 16-bit guest-state fields. */
449 VMX_VMCS16_GUEST_ES_SEL,
450 VMX_VMCS16_GUEST_CS_SEL,
451 VMX_VMCS16_GUEST_SS_SEL,
452 VMX_VMCS16_GUEST_DS_SEL,
453 VMX_VMCS16_GUEST_FS_SEL,
454 VMX_VMCS16_GUEST_GS_SEL,
455 VMX_VMCS16_GUEST_LDTR_SEL,
456 VMX_VMCS16_GUEST_TR_SEL,
457 VMX_VMCS16_GUEST_INTR_STATUS,
458 VMX_VMCS16_GUEST_PML_INDEX,
459
460 /* 16-bits host-state fields. */
461 VMX_VMCS16_HOST_ES_SEL,
462 VMX_VMCS16_HOST_CS_SEL,
463 VMX_VMCS16_HOST_SS_SEL,
464 VMX_VMCS16_HOST_DS_SEL,
465 VMX_VMCS16_HOST_FS_SEL,
466 VMX_VMCS16_HOST_GS_SEL,
467 VMX_VMCS16_HOST_TR_SEL,
468
469 /* 64-bit control fields. */
470 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
471 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
472 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
473 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
474 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
475 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
476 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
477 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
478 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
479 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
480 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
481 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
482 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
483 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
484 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
485 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
486 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
487 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
488 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
489 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
490 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
491 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
492 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
493 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
494 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
495 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
496 VMX_VMCS64_CTRL_EPTP_FULL,
497 VMX_VMCS64_CTRL_EPTP_HIGH,
498 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
499 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
500 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
501 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
502 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
503 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
504 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
505 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
506 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
507 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
508 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
509 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
510 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
511 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
512 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
513 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
514 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
515 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
516 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
517 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
518 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
519 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
520
521 /* 64-bit read-only data fields. */
522 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
523 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
524
525 /* 64-bit guest-state fields. */
526 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
527 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
528 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
529 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
530 VMX_VMCS64_GUEST_PAT_FULL,
531 VMX_VMCS64_GUEST_PAT_HIGH,
532 VMX_VMCS64_GUEST_EFER_FULL,
533 VMX_VMCS64_GUEST_EFER_HIGH,
534 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
535 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
536 VMX_VMCS64_GUEST_PDPTE0_FULL,
537 VMX_VMCS64_GUEST_PDPTE0_HIGH,
538 VMX_VMCS64_GUEST_PDPTE1_FULL,
539 VMX_VMCS64_GUEST_PDPTE1_HIGH,
540 VMX_VMCS64_GUEST_PDPTE2_FULL,
541 VMX_VMCS64_GUEST_PDPTE2_HIGH,
542 VMX_VMCS64_GUEST_PDPTE3_FULL,
543 VMX_VMCS64_GUEST_PDPTE3_HIGH,
544 VMX_VMCS64_GUEST_BNDCFGS_FULL,
545 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
546
547 /* 64-bit host-state fields. */
548 VMX_VMCS64_HOST_PAT_FULL,
549 VMX_VMCS64_HOST_PAT_HIGH,
550 VMX_VMCS64_HOST_EFER_FULL,
551 VMX_VMCS64_HOST_EFER_HIGH,
552 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
553 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
554
555 /* 32-bit control fields. */
556 VMX_VMCS32_CTRL_PIN_EXEC,
557 VMX_VMCS32_CTRL_PROC_EXEC,
558 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
559 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
560 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
561 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
562 VMX_VMCS32_CTRL_EXIT,
563 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
564 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
565 VMX_VMCS32_CTRL_ENTRY,
566 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
567 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
568 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
569 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
570 VMX_VMCS32_CTRL_TPR_THRESHOLD,
571 VMX_VMCS32_CTRL_PROC_EXEC2,
572 VMX_VMCS32_CTRL_PLE_GAP,
573 VMX_VMCS32_CTRL_PLE_WINDOW,
574
575 /* 32-bits read-only fields. */
576 VMX_VMCS32_RO_VM_INSTR_ERROR,
577 VMX_VMCS32_RO_EXIT_REASON,
578 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
579 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
580 VMX_VMCS32_RO_IDT_VECTORING_INFO,
581 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
582 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
583 VMX_VMCS32_RO_EXIT_INSTR_INFO,
584
585 /* 32-bit guest-state fields. */
586 VMX_VMCS32_GUEST_ES_LIMIT,
587 VMX_VMCS32_GUEST_CS_LIMIT,
588 VMX_VMCS32_GUEST_SS_LIMIT,
589 VMX_VMCS32_GUEST_DS_LIMIT,
590 VMX_VMCS32_GUEST_FS_LIMIT,
591 VMX_VMCS32_GUEST_GS_LIMIT,
592 VMX_VMCS32_GUEST_LDTR_LIMIT,
593 VMX_VMCS32_GUEST_TR_LIMIT,
594 VMX_VMCS32_GUEST_GDTR_LIMIT,
595 VMX_VMCS32_GUEST_IDTR_LIMIT,
596 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
597 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
598 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
599 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
602 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
603 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
604 VMX_VMCS32_GUEST_INT_STATE,
605 VMX_VMCS32_GUEST_ACTIVITY_STATE,
606 VMX_VMCS32_GUEST_SMBASE,
607 VMX_VMCS32_GUEST_SYSENTER_CS,
608 VMX_VMCS32_PREEMPT_TIMER_VALUE,
609
610 /* 32-bit host-state fields. */
611 VMX_VMCS32_HOST_SYSENTER_CS,
612
613 /* Natural-width control fields. */
614 VMX_VMCS_CTRL_CR0_MASK,
615 VMX_VMCS_CTRL_CR4_MASK,
616 VMX_VMCS_CTRL_CR0_READ_SHADOW,
617 VMX_VMCS_CTRL_CR4_READ_SHADOW,
618 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
619 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
620 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
621 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
622
623 /* Natural-width read-only data fields. */
624 VMX_VMCS_RO_EXIT_QUALIFICATION,
625 VMX_VMCS_RO_IO_RCX,
626 VMX_VMCS_RO_IO_RSI,
627 VMX_VMCS_RO_IO_RDI,
628 VMX_VMCS_RO_IO_RIP,
629 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
630
631 /* Natural-width guest-state field */
632 VMX_VMCS_GUEST_CR0,
633 VMX_VMCS_GUEST_CR3,
634 VMX_VMCS_GUEST_CR4,
635 VMX_VMCS_GUEST_ES_BASE,
636 VMX_VMCS_GUEST_CS_BASE,
637 VMX_VMCS_GUEST_SS_BASE,
638 VMX_VMCS_GUEST_DS_BASE,
639 VMX_VMCS_GUEST_FS_BASE,
640 VMX_VMCS_GUEST_GS_BASE,
641 VMX_VMCS_GUEST_LDTR_BASE,
642 VMX_VMCS_GUEST_TR_BASE,
643 VMX_VMCS_GUEST_GDTR_BASE,
644 VMX_VMCS_GUEST_IDTR_BASE,
645 VMX_VMCS_GUEST_DR7,
646 VMX_VMCS_GUEST_RSP,
647 VMX_VMCS_GUEST_RIP,
648 VMX_VMCS_GUEST_RFLAGS,
649 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
650 VMX_VMCS_GUEST_SYSENTER_ESP,
651 VMX_VMCS_GUEST_SYSENTER_EIP,
652
653 /* Natural-width host-state fields */
654 VMX_VMCS_HOST_CR0,
655 VMX_VMCS_HOST_CR3,
656 VMX_VMCS_HOST_CR4,
657 VMX_VMCS_HOST_FS_BASE,
658 VMX_VMCS_HOST_GS_BASE,
659 VMX_VMCS_HOST_TR_BASE,
660 VMX_VMCS_HOST_GDTR_BASE,
661 VMX_VMCS_HOST_IDTR_BASE,
662 VMX_VMCS_HOST_SYSENTER_ESP,
663 VMX_VMCS_HOST_SYSENTER_EIP,
664 VMX_VMCS_HOST_RSP,
665 VMX_VMCS_HOST_RIP
666};
667#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
668
669static const uint32_t g_aVmcsSegBase[] =
670{
671 VMX_VMCS_GUEST_ES_BASE,
672 VMX_VMCS_GUEST_CS_BASE,
673 VMX_VMCS_GUEST_SS_BASE,
674 VMX_VMCS_GUEST_DS_BASE,
675 VMX_VMCS_GUEST_FS_BASE,
676 VMX_VMCS_GUEST_GS_BASE
677};
678static const uint32_t g_aVmcsSegSel[] =
679{
680 VMX_VMCS16_GUEST_ES_SEL,
681 VMX_VMCS16_GUEST_CS_SEL,
682 VMX_VMCS16_GUEST_SS_SEL,
683 VMX_VMCS16_GUEST_DS_SEL,
684 VMX_VMCS16_GUEST_FS_SEL,
685 VMX_VMCS16_GUEST_GS_SEL
686};
687static const uint32_t g_aVmcsSegLimit[] =
688{
689 VMX_VMCS32_GUEST_ES_LIMIT,
690 VMX_VMCS32_GUEST_CS_LIMIT,
691 VMX_VMCS32_GUEST_SS_LIMIT,
692 VMX_VMCS32_GUEST_DS_LIMIT,
693 VMX_VMCS32_GUEST_FS_LIMIT,
694 VMX_VMCS32_GUEST_GS_LIMIT
695};
696static const uint32_t g_aVmcsSegAttr[] =
697{
698 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
699 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
700 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
701 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
702 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
703 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
704};
705AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
706AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
707AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
708AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
709
710#ifdef HMVMX_USE_FUNCTION_TABLE
711/**
712 * VMX_EXIT dispatch table.
713 */
714static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
715{
716 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
717 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
718 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
719 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
720 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
721 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
722 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
723 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
724 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
725 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
726 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
727 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
728 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
729 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
730 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
731 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
732 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
733 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
734 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
735#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
736 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
737 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
738 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
739 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
740 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
741 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
742 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
743 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
744 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
745#else
746 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
747 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
748 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
749 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
750 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
751 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
752 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
753 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
754 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
755#endif
756 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
757 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
758 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
759 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
760 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
761 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
762 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
763 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
764 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
765 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
766 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
767 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
768 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
769 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
770 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
771 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
772 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
773 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
774 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
775 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
776 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
777 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
778 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
779 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
780 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
781#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
782 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
783#else
784 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
785#endif
786 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
787 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
788 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
789 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
790 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
791 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
792 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
793 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
794 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
795 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
796 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
797 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
798 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
799 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
800 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
801};
802#endif /* HMVMX_USE_FUNCTION_TABLE */
803
804#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
805static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
806{
807 /* 0 */ "(Not Used)",
808 /* 1 */ "VMCALL executed in VMX root operation.",
809 /* 2 */ "VMCLEAR with invalid physical address.",
810 /* 3 */ "VMCLEAR with VMXON pointer.",
811 /* 4 */ "VMLAUNCH with non-clear VMCS.",
812 /* 5 */ "VMRESUME with non-launched VMCS.",
813 /* 6 */ "VMRESUME after VMXOFF",
814 /* 7 */ "VM-entry with invalid control fields.",
815 /* 8 */ "VM-entry with invalid host state fields.",
816 /* 9 */ "VMPTRLD with invalid physical address.",
817 /* 10 */ "VMPTRLD with VMXON pointer.",
818 /* 11 */ "VMPTRLD with incorrect revision identifier.",
819 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
820 /* 13 */ "VMWRITE to read-only VMCS component.",
821 /* 14 */ "(Not Used)",
822 /* 15 */ "VMXON executed in VMX root operation.",
823 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
824 /* 17 */ "VM-entry with non-launched executing VMCS.",
825 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
826 /* 19 */ "VMCALL with non-clear VMCS.",
827 /* 20 */ "VMCALL with invalid VM-exit control fields.",
828 /* 21 */ "(Not Used)",
829 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
830 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
831 /* 24 */ "VMCALL with invalid SMM-monitor features.",
832 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
833 /* 26 */ "VM-entry with events blocked by MOV SS.",
834 /* 27 */ "(Not Used)",
835 /* 28 */ "Invalid operand to INVEPT/INVVPID."
836};
837#endif /* VBOX_STRICT && LOG_ENABLED */
838
839
840/**
841 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
842 *
843 * Any bit set in this mask is owned by the host/hypervisor and would cause a
844 * VM-exit when modified by the guest.
845 *
846 * @returns The static CR0 guest/host mask.
847 * @param pVCpu The cross context virtual CPU structure.
848 */
849DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPUCC pVCpu)
850{
851 /*
852 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
853 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
854 */
855 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
856 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
857 * and @bugref{6944}. */
858 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
859 return ( X86_CR0_PE
860 | X86_CR0_NE
861 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
862 | X86_CR0_PG
863 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
864 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
865 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
866}
867
868
869/**
870 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
871 *
872 * Any bit set in this mask is owned by the host/hypervisor and would cause a
873 * VM-exit when modified by the guest.
874 *
875 * @returns The static CR4 guest/host mask.
876 * @param pVCpu The cross context virtual CPU structure.
877 */
878DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
879{
880 /*
881 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
882 * these bits are reserved on hardware that does not support them. Since the
883 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
884 * these bits and handle it depending on whether we expose them to the guest.
885 */
886 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
887 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
888 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
889 return ( X86_CR4_VMXE
890 | X86_CR4_VME
891 | X86_CR4_PAE
892 | X86_CR4_PGE
893 | X86_CR4_PSE
894 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
895 | (fPcid ? X86_CR4_PCIDE : 0));
896}
897
898
899/**
900 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
901 * area.
902 *
903 * @returns @c true if it's different, @c false otherwise.
904 * @param pVmcsInfo The VMCS info. object.
905 */
906DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
907{
908 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
909 && pVmcsInfo->pvGuestMsrStore);
910}
911
912
913/**
914 * Sets the given Processor-based VM-execution controls.
915 *
916 * @param pVmxTransient The VMX-transient structure.
917 * @param uProcCtls The Processor-based VM-execution controls to set.
918 */
919static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
920{
921 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
922 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
923 {
924 pVmcsInfo->u32ProcCtls |= uProcCtls;
925 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
926 AssertRC(rc);
927 }
928}
929
930
931/**
932 * Removes the given Processor-based VM-execution controls.
933 *
934 * @param pVCpu The cross context virtual CPU structure.
935 * @param pVmxTransient The VMX-transient structure.
936 * @param uProcCtls The Processor-based VM-execution controls to remove.
937 *
938 * @remarks When executing a nested-guest, this will not remove any of the specified
939 * controls if the guest hypervisor has set any one of them.
940 */
941static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
942{
943 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
944 if (pVmcsInfo->u32ProcCtls & uProcCtls)
945 {
946#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
947 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
948 ? true
949 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
950#else
951 NOREF(pVCpu);
952 bool const fRemoveCtls = true;
953#endif
954 if (fRemoveCtls)
955 {
956 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
957 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
958 AssertRC(rc);
959 }
960 }
961}
962
963
964/**
965 * Sets the TSC offset for the current VMCS.
966 *
967 * @param uTscOffset The TSC offset to set.
968 * @param pVmcsInfo The VMCS info. object.
969 */
970static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
971{
972 if (pVmcsInfo->u64TscOffset != uTscOffset)
973 {
974 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
975 AssertRC(rc);
976 pVmcsInfo->u64TscOffset = uTscOffset;
977 }
978}
979
980
981/**
982 * Adds one or more exceptions to the exception bitmap and commits it to the current
983 * VMCS.
984 *
985 * @param pVmxTransient The VMX-transient structure.
986 * @param uXcptMask The exception(s) to add.
987 */
988static void hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
989{
990 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
991 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
992 if ((uXcptBitmap & uXcptMask) != uXcptMask)
993 {
994 uXcptBitmap |= uXcptMask;
995 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
996 AssertRC(rc);
997 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
998 }
999}
1000
1001
1002/**
1003 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1004 *
1005 * @param pVmxTransient The VMX-transient structure.
1006 * @param uXcpt The exception to add.
1007 */
1008static void hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1009{
1010 Assert(uXcpt <= X86_XCPT_LAST);
1011 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1012}
1013
1014
1015/**
1016 * Remove one or more exceptions from the exception bitmap and commits it to the
1017 * current VMCS.
1018 *
1019 * This takes care of not removing the exception intercept if a nested-guest
1020 * requires the exception to be intercepted.
1021 *
1022 * @returns VBox status code.
1023 * @param pVCpu The cross context virtual CPU structure.
1024 * @param pVmxTransient The VMX-transient structure.
1025 * @param uXcptMask The exception(s) to remove.
1026 */
1027static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1028{
1029 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1030 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1031 if (u32XcptBitmap & uXcptMask)
1032 {
1033#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1034 if (!pVmxTransient->fIsNestedGuest)
1035 { /* likely */ }
1036 else
1037 {
1038 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1039 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1040 }
1041#endif
1042#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1043 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1044 | RT_BIT(X86_XCPT_DE)
1045 | RT_BIT(X86_XCPT_NM)
1046 | RT_BIT(X86_XCPT_TS)
1047 | RT_BIT(X86_XCPT_UD)
1048 | RT_BIT(X86_XCPT_NP)
1049 | RT_BIT(X86_XCPT_SS)
1050 | RT_BIT(X86_XCPT_GP)
1051 | RT_BIT(X86_XCPT_PF)
1052 | RT_BIT(X86_XCPT_MF));
1053#elif defined(HMVMX_ALWAYS_TRAP_PF)
1054 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1055#endif
1056 if (uXcptMask)
1057 {
1058 /* Validate we are not removing any essential exception intercepts. */
1059 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1060 NOREF(pVCpu);
1061 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1062 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1063
1064 /* Remove it from the exception bitmap. */
1065 u32XcptBitmap &= ~uXcptMask;
1066
1067 /* Commit and update the cache if necessary. */
1068 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1069 {
1070 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1071 AssertRC(rc);
1072 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1073 }
1074 }
1075 }
1076 return VINF_SUCCESS;
1077}
1078
1079
1080/**
1081 * Remove an exceptions from the exception bitmap and commits it to the current
1082 * VMCS.
1083 *
1084 * @returns VBox status code.
1085 * @param pVCpu The cross context virtual CPU structure.
1086 * @param pVmxTransient The VMX-transient structure.
1087 * @param uXcpt The exception to remove.
1088 */
1089static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1090{
1091 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1092}
1093
1094
1095/**
1096 * Loads the VMCS specified by the VMCS info. object.
1097 *
1098 * @returns VBox status code.
1099 * @param pVmcsInfo The VMCS info. object.
1100 *
1101 * @remarks Can be called with interrupts disabled.
1102 */
1103static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1104{
1105 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1106 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1107
1108 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1109 if (RT_SUCCESS(rc))
1110 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1111 return rc;
1112}
1113
1114
1115/**
1116 * Clears the VMCS specified by the VMCS info. object.
1117 *
1118 * @returns VBox status code.
1119 * @param pVmcsInfo The VMCS info. object.
1120 *
1121 * @remarks Can be called with interrupts disabled.
1122 */
1123static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1124{
1125 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1126 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1127
1128 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1129 if (RT_SUCCESS(rc))
1130 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1131 return rc;
1132}
1133
1134
1135#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1136/**
1137 * Loads the shadow VMCS specified by the VMCS info. object.
1138 *
1139 * @returns VBox status code.
1140 * @param pVmcsInfo The VMCS info. object.
1141 *
1142 * @remarks Can be called with interrupts disabled.
1143 */
1144static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1145{
1146 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1147 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1148
1149 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1150 if (RT_SUCCESS(rc))
1151 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1152 return rc;
1153}
1154
1155
1156/**
1157 * Clears the shadow VMCS specified by the VMCS info. object.
1158 *
1159 * @returns VBox status code.
1160 * @param pVmcsInfo The VMCS info. object.
1161 *
1162 * @remarks Can be called with interrupts disabled.
1163 */
1164static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1165{
1166 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1167 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1168
1169 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1170 if (RT_SUCCESS(rc))
1171 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1172 return rc;
1173}
1174
1175
1176/**
1177 * Switches from and to the specified VMCSes.
1178 *
1179 * @returns VBox status code.
1180 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1181 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1182 *
1183 * @remarks Called with interrupts disabled.
1184 */
1185static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1186{
1187 /*
1188 * Clear the VMCS we are switching out if it has not already been cleared.
1189 * This will sync any CPU internal data back to the VMCS.
1190 */
1191 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1192 {
1193 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1194 if (RT_SUCCESS(rc))
1195 {
1196 /*
1197 * The shadow VMCS, if any, would not be active at this point since we
1198 * would have cleared it while importing the virtual hardware-virtualization
1199 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1200 * clear the shadow VMCS here, just assert for safety.
1201 */
1202 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1203 }
1204 else
1205 return rc;
1206 }
1207
1208 /*
1209 * Clear the VMCS we are switching to if it has not already been cleared.
1210 * This will initialize the VMCS launch state to "clear" required for loading it.
1211 *
1212 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1213 */
1214 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1215 {
1216 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1217 if (RT_SUCCESS(rc))
1218 { /* likely */ }
1219 else
1220 return rc;
1221 }
1222
1223 /*
1224 * Finally, load the VMCS we are switching to.
1225 */
1226 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1227}
1228
1229
1230/**
1231 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1232 * caller.
1233 *
1234 * @returns VBox status code.
1235 * @param pVCpu The cross context virtual CPU structure.
1236 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1237 * true) or guest VMCS (pass false).
1238 */
1239static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1240{
1241 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1242 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1243
1244 PVMXVMCSINFO pVmcsInfoFrom;
1245 PVMXVMCSINFO pVmcsInfoTo;
1246 if (fSwitchToNstGstVmcs)
1247 {
1248 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1249 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1250 }
1251 else
1252 {
1253 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1254 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1255 }
1256
1257 /*
1258 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1259 * preemption hook code path acquires the current VMCS.
1260 */
1261 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1262
1263 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1264 if (RT_SUCCESS(rc))
1265 {
1266 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1267
1268 /*
1269 * If we are switching to a VMCS that was executed on a different host CPU or was
1270 * never executed before, flag that we need to export the host state before executing
1271 * guest/nested-guest code using hardware-assisted VMX.
1272 *
1273 * This could probably be done in a preemptible context since the preemption hook
1274 * will flag the necessary change in host context. However, since preemption is
1275 * already disabled and to avoid making assumptions about host specific code in
1276 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1277 * disabled.
1278 */
1279 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1280 { /* likely */ }
1281 else
1282 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1283
1284 ASMSetFlags(fEFlags);
1285
1286 /*
1287 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1288 * flag that we need to update the host MSR values there. Even if we decide in the
1289 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1290 * if its content differs, we would have to update the host MSRs anyway.
1291 */
1292 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1293 }
1294 else
1295 ASMSetFlags(fEFlags);
1296 return rc;
1297}
1298#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1299
1300
1301/**
1302 * Updates the VM's last error record.
1303 *
1304 * If there was a VMX instruction error, reads the error data from the VMCS and
1305 * updates VCPU's last error record as well.
1306 *
1307 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1308 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1309 * VERR_VMX_INVALID_VMCS_FIELD.
1310 * @param rc The error code.
1311 */
1312static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1313{
1314 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1315 || rc == VERR_VMX_UNABLE_TO_START_VM)
1316 {
1317 AssertPtrReturnVoid(pVCpu);
1318 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1319 }
1320 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1321}
1322
1323
1324#ifdef VBOX_STRICT
1325/**
1326 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1327 * transient structure.
1328 *
1329 * @param pVmxTransient The VMX-transient structure.
1330 */
1331DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1332{
1333 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1334 AssertRC(rc);
1335}
1336
1337
1338/**
1339 * Reads the VM-entry exception error code field from the VMCS into
1340 * the VMX transient structure.
1341 *
1342 * @param pVmxTransient The VMX-transient structure.
1343 */
1344DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1345{
1346 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1347 AssertRC(rc);
1348}
1349
1350
1351/**
1352 * Reads the VM-entry exception error code field from the VMCS into
1353 * the VMX transient structure.
1354 *
1355 * @param pVmxTransient The VMX-transient structure.
1356 */
1357DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1358{
1359 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1360 AssertRC(rc);
1361}
1362#endif /* VBOX_STRICT */
1363
1364
1365/**
1366 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1367 * transient structure.
1368 *
1369 * @param pVmxTransient The VMX-transient structure.
1370 */
1371DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1372{
1373 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1374 {
1375 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1376 AssertRC(rc);
1377 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1378 }
1379}
1380
1381
1382/**
1383 * Reads the VM-exit interruption error code from the VMCS into the VMX
1384 * transient structure.
1385 *
1386 * @param pVmxTransient The VMX-transient structure.
1387 */
1388DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1389{
1390 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1391 {
1392 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1393 AssertRC(rc);
1394 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1395 }
1396}
1397
1398
1399/**
1400 * Reads the VM-exit instruction length field from the VMCS into the VMX
1401 * transient structure.
1402 *
1403 * @param pVmxTransient The VMX-transient structure.
1404 */
1405DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1406{
1407 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1408 {
1409 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1410 AssertRC(rc);
1411 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1412 }
1413}
1414
1415
1416/**
1417 * Reads the VM-exit instruction-information field from the VMCS into
1418 * the VMX transient structure.
1419 *
1420 * @param pVmxTransient The VMX-transient structure.
1421 */
1422DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1423{
1424 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1425 {
1426 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1427 AssertRC(rc);
1428 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1429 }
1430}
1431
1432
1433/**
1434 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1435 *
1436 * @param pVmxTransient The VMX-transient structure.
1437 */
1438DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1439{
1440 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1441 {
1442 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1443 AssertRC(rc);
1444 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1445 }
1446}
1447
1448
1449/**
1450 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1451 *
1452 * @param pVmxTransient The VMX-transient structure.
1453 */
1454DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1455{
1456 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1457 {
1458 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1459 AssertRC(rc);
1460 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1461 }
1462}
1463
1464
1465/**
1466 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1467 *
1468 * @param pVmxTransient The VMX-transient structure.
1469 */
1470DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1471{
1472 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1473 {
1474 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1475 AssertRC(rc);
1476 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1477 }
1478}
1479
1480#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1481/**
1482 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1483 * structure.
1484 *
1485 * @param pVmxTransient The VMX-transient structure.
1486 */
1487DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1488{
1489 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1490 {
1491 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1492 AssertRC(rc);
1493 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1494 }
1495}
1496#endif
1497
1498/**
1499 * Reads the IDT-vectoring information field from the VMCS into the VMX
1500 * transient structure.
1501 *
1502 * @param pVmxTransient The VMX-transient structure.
1503 *
1504 * @remarks No-long-jump zone!!!
1505 */
1506DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1507{
1508 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1509 {
1510 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1511 AssertRC(rc);
1512 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1513 }
1514}
1515
1516
1517/**
1518 * Reads the IDT-vectoring error code from the VMCS into the VMX
1519 * transient structure.
1520 *
1521 * @param pVmxTransient The VMX-transient structure.
1522 */
1523DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1524{
1525 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1526 {
1527 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1528 AssertRC(rc);
1529 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1530 }
1531}
1532
1533#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1534/**
1535 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1536 *
1537 * @param pVmxTransient The VMX-transient structure.
1538 */
1539static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1540{
1541 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1542 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1543 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1544 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1545 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1546 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1547 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1548 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1549 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1550 AssertRC(rc);
1551 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1552 | HMVMX_READ_EXIT_INSTR_LEN
1553 | HMVMX_READ_EXIT_INSTR_INFO
1554 | HMVMX_READ_IDT_VECTORING_INFO
1555 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1556 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1557 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1558 | HMVMX_READ_GUEST_LINEAR_ADDR
1559 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1560}
1561#endif
1562
1563/**
1564 * Enters VMX root mode operation on the current CPU.
1565 *
1566 * @returns VBox status code.
1567 * @param pVM The cross context VM structure. Can be
1568 * NULL, after a resume.
1569 * @param HCPhysCpuPage Physical address of the VMXON region.
1570 * @param pvCpuPage Pointer to the VMXON region.
1571 */
1572static int hmR0VmxEnterRootMode(PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1573{
1574 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1575 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1576 Assert(pvCpuPage);
1577 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1578
1579 if (pVM)
1580 {
1581 /* Write the VMCS revision identifier to the VMXON region. */
1582 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1583 }
1584
1585 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1586 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1587
1588 /* Enable the VMX bit in CR4 if necessary. */
1589 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1590
1591 /* Enter VMX root mode. */
1592 int rc = VMXEnable(HCPhysCpuPage);
1593 if (RT_FAILURE(rc))
1594 {
1595 if (!(uOldCr4 & X86_CR4_VMXE))
1596 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1597
1598 if (pVM)
1599 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1600 }
1601
1602 /* Restore interrupts. */
1603 ASMSetFlags(fEFlags);
1604 return rc;
1605}
1606
1607
1608/**
1609 * Exits VMX root mode operation on the current CPU.
1610 *
1611 * @returns VBox status code.
1612 */
1613static int hmR0VmxLeaveRootMode(void)
1614{
1615 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1616
1617 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1618 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1619
1620 /* If we're for some reason not in VMX root mode, then don't leave it. */
1621 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1622
1623 int rc;
1624 if (uHostCr4 & X86_CR4_VMXE)
1625 {
1626 /* Exit VMX root mode and clear the VMX bit in CR4. */
1627 VMXDisable();
1628 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1629 rc = VINF_SUCCESS;
1630 }
1631 else
1632 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1633
1634 /* Restore interrupts. */
1635 ASMSetFlags(fEFlags);
1636 return rc;
1637}
1638
1639
1640/**
1641 * Allocates and maps a physically contiguous page. The allocated page is
1642 * zero'd out (used by various VT-x structures).
1643 *
1644 * @returns IPRT status code.
1645 * @param pMemObj Pointer to the ring-0 memory object.
1646 * @param ppVirt Where to store the virtual address of the allocation.
1647 * @param pHCPhys Where to store the physical address of the allocation.
1648 */
1649static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1650{
1651 AssertPtr(pMemObj);
1652 AssertPtr(ppVirt);
1653 AssertPtr(pHCPhys);
1654 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1655 if (RT_FAILURE(rc))
1656 return rc;
1657 *ppVirt = RTR0MemObjAddress(*pMemObj);
1658 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1659 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1660 return VINF_SUCCESS;
1661}
1662
1663
1664/**
1665 * Frees and unmaps an allocated, physical page.
1666 *
1667 * @param pMemObj Pointer to the ring-0 memory object.
1668 * @param ppVirt Where to re-initialize the virtual address of allocation as
1669 * 0.
1670 * @param pHCPhys Where to re-initialize the physical address of the
1671 * allocation as 0.
1672 */
1673static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1674{
1675 AssertPtr(pMemObj);
1676 AssertPtr(ppVirt);
1677 AssertPtr(pHCPhys);
1678 /* NULL is valid, accepted and ignored by the free function below. */
1679 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1680 *pMemObj = NIL_RTR0MEMOBJ;
1681 *ppVirt = NULL;
1682 *pHCPhys = NIL_RTHCPHYS;
1683}
1684
1685
1686/**
1687 * Initializes a VMCS info. object.
1688 *
1689 * @param pVmcsInfo The VMCS info. object.
1690 */
1691static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1692{
1693 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1694
1695 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1696 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1697 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1698 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1699 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1700 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1701 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1702 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1703 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1704 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1705 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1706 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1707 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1708 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1709 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1710 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1711 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1712}
1713
1714
1715/**
1716 * Frees the VT-x structures for a VMCS info. object.
1717 *
1718 * @param pVM The cross context VM structure.
1719 * @param pVmcsInfo The VMCS info. object.
1720 */
1721static void hmR0VmxFreeVmcsInfo(PVMCC pVM, PVMXVMCSINFO pVmcsInfo)
1722{
1723 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1724
1725#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1726 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1727 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1728#endif
1729
1730 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1731 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1732
1733 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1734 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1735 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1736
1737 hmR0VmxInitVmcsInfo(pVmcsInfo);
1738}
1739
1740
1741/**
1742 * Allocates the VT-x structures for a VMCS info. object.
1743 *
1744 * @returns VBox status code.
1745 * @param pVCpu The cross context virtual CPU structure.
1746 * @param pVmcsInfo The VMCS info. object.
1747 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1748 */
1749static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1750{
1751 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1752
1753 /* Allocate the guest VM control structure (VMCS). */
1754 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1755 if (RT_SUCCESS(rc))
1756 {
1757 if (!fIsNstGstVmcs)
1758 {
1759#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1760 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1761 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1762#endif
1763 if (RT_SUCCESS(rc))
1764 {
1765 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1766 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1767 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1768 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1769 }
1770 }
1771 else
1772 {
1773 /* We don't yet support exposing VMCS shadowing to the guest. */
1774 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1775 Assert(!pVmcsInfo->pvShadowVmcs);
1776
1777 /* Get the allocated virtual-APIC page from CPUM. */
1778 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1779 {
1780 /** @todo NSTVMX: Get rid of this. There is no need to allocate a separate HC
1781 * page for this. Use the one provided by the nested-guest directly. */
1782 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1783 &pVmcsInfo->HCPhysVirtApic);
1784 Assert(pVmcsInfo->pbVirtApic);
1785 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1786 }
1787 }
1788
1789 if (RT_SUCCESS(rc))
1790 {
1791 /*
1792 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1793 * transparent accesses of specific MSRs.
1794 *
1795 * If the condition for enabling MSR bitmaps changes here, don't forget to
1796 * update HMIsMsrBitmapActive().
1797 *
1798 * We don't share MSR bitmaps between the guest and nested-guest as we then
1799 * don't need to care about carefully restoring the guest MSR bitmap.
1800 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1801 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1802 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1803 * we do that later while merging VMCS.
1804 */
1805 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1806 {
1807 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1808 if ( RT_SUCCESS(rc)
1809 && !fIsNstGstVmcs)
1810 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1811 }
1812
1813 if (RT_SUCCESS(rc))
1814 {
1815 /*
1816 * Allocate the VM-entry MSR-load area for the guest MSRs.
1817 *
1818 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1819 * the guest and nested-guest.
1820 */
1821 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1822 &pVmcsInfo->HCPhysGuestMsrLoad);
1823 if (RT_SUCCESS(rc))
1824 {
1825 /*
1826 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1827 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1828 */
1829 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1830 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1831 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1832
1833 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1834 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1835 &pVmcsInfo->HCPhysHostMsrLoad);
1836 }
1837 }
1838 }
1839 }
1840
1841 return rc;
1842}
1843
1844
1845/**
1846 * Free all VT-x structures for the VM.
1847 *
1848 * @returns IPRT status code.
1849 * @param pVM The cross context VM structure.
1850 */
1851static void hmR0VmxStructsFree(PVMCC pVM)
1852{
1853#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1854 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1855#endif
1856 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1857
1858#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1859 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1860 {
1861 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1862 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1863 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1864 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1865 }
1866#endif
1867
1868 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1869 {
1870 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1871 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1872 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1873#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1874 if (pVM->cpum.ro.GuestFeatures.fVmx)
1875 {
1876 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1877 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1878 }
1879#endif
1880 }
1881}
1882
1883
1884/**
1885 * Allocate all VT-x structures for the VM.
1886 *
1887 * @returns IPRT status code.
1888 * @param pVM The cross context VM structure.
1889 */
1890static int hmR0VmxStructsAlloc(PVMCC pVM)
1891{
1892 /*
1893 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1894 * The VMCS size cannot be more than 4096 bytes.
1895 *
1896 * See Intel spec. Appendix A.1 "Basic VMX Information".
1897 */
1898 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1899 if (cbVmcs <= X86_PAGE_4K_SIZE)
1900 { /* likely */ }
1901 else
1902 {
1903 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1904 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1905 }
1906
1907 /*
1908 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1909 */
1910#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1911 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1912 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1913 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1914#endif
1915
1916 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1917 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1918 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1919
1920 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1921 {
1922 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1923 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1924 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1925 }
1926
1927 /*
1928 * Allocate per-VM VT-x structures.
1929 */
1930 int rc = VINF_SUCCESS;
1931#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1932 /* Allocate crash-dump magic scratch page. */
1933 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1934 if (RT_FAILURE(rc))
1935 {
1936 hmR0VmxStructsFree(pVM);
1937 return rc;
1938 }
1939 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1940 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1941#endif
1942
1943 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1944 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1945 {
1946 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1947 &pVM->hm.s.vmx.HCPhysApicAccess);
1948 if (RT_FAILURE(rc))
1949 {
1950 hmR0VmxStructsFree(pVM);
1951 return rc;
1952 }
1953 }
1954
1955#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1956 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1957 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1958 {
1959 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1960 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1961 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1962 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1963 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1964 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1965 {
1966 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1967 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1968 if (RT_SUCCESS(rc))
1969 {
1970 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1971 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1972 }
1973 }
1974 else
1975 rc = VERR_NO_MEMORY;
1976
1977 if (RT_FAILURE(rc))
1978 {
1979 hmR0VmxStructsFree(pVM);
1980 return rc;
1981 }
1982 }
1983#endif
1984
1985 /*
1986 * Initialize per-VCPU VT-x structures.
1987 */
1988 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1989 {
1990 /* Allocate the guest VMCS structures. */
1991 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1992 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1993 if (RT_SUCCESS(rc))
1994 {
1995#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1996 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1997 if (pVM->cpum.ro.GuestFeatures.fVmx)
1998 {
1999 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2000 if (RT_SUCCESS(rc))
2001 { /* likely */ }
2002 else
2003 break;
2004 }
2005#endif
2006 }
2007 else
2008 break;
2009 }
2010
2011 if (RT_FAILURE(rc))
2012 {
2013 hmR0VmxStructsFree(pVM);
2014 return rc;
2015 }
2016
2017 return VINF_SUCCESS;
2018}
2019
2020#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2021/**
2022 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2023 *
2024 * @returns @c true if the MSR is intercepted, @c false otherwise.
2025 * @param pvMsrBitmap The MSR bitmap.
2026 * @param offMsr The MSR byte offset.
2027 * @param iBit The bit offset from the byte offset.
2028 */
2029DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2030{
2031 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2032 Assert(pbMsrBitmap);
2033 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2034 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2035}
2036#endif
2037
2038/**
2039 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2040 *
2041 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2042 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2043 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2044 * the read/write access of this MSR.
2045 *
2046 * @param pVCpu The cross context virtual CPU structure.
2047 * @param pVmcsInfo The VMCS info. object.
2048 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2049 * @param idMsr The MSR value.
2050 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2051 * include both a read -and- a write permission!
2052 *
2053 * @sa CPUMGetVmxMsrPermission.
2054 * @remarks Can be called with interrupts disabled.
2055 */
2056static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2057{
2058 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2059 Assert(pbMsrBitmap);
2060 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2061
2062 /*
2063 * MSR-bitmap Layout:
2064 * Byte index MSR range Interpreted as
2065 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2066 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2067 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2068 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2069 *
2070 * A bit corresponding to an MSR within the above range causes a VM-exit
2071 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2072 * the MSR range, it always cause a VM-exit.
2073 *
2074 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2075 */
2076 uint16_t const offBitmapRead = 0;
2077 uint16_t const offBitmapWrite = 0x800;
2078 uint16_t offMsr;
2079 int32_t iBit;
2080 if (idMsr <= UINT32_C(0x00001fff))
2081 {
2082 offMsr = 0;
2083 iBit = idMsr;
2084 }
2085 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2086 {
2087 offMsr = 0x400;
2088 iBit = idMsr - UINT32_C(0xc0000000);
2089 }
2090 else
2091 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2092
2093 /*
2094 * Set the MSR read permission.
2095 */
2096 uint16_t const offMsrRead = offBitmapRead + offMsr;
2097 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2098 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2099 {
2100#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2101 bool const fClear = !fIsNstGstVmcs ? true
2102 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2103#else
2104 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2105 bool const fClear = true;
2106#endif
2107 if (fClear)
2108 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2109 }
2110 else
2111 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2112
2113 /*
2114 * Set the MSR write permission.
2115 */
2116 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2117 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2118 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2119 {
2120#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2121 bool const fClear = !fIsNstGstVmcs ? true
2122 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2123#else
2124 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2125 bool const fClear = true;
2126#endif
2127 if (fClear)
2128 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2129 }
2130 else
2131 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2132}
2133
2134
2135/**
2136 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2137 * area.
2138 *
2139 * @returns VBox status code.
2140 * @param pVCpu The cross context virtual CPU structure.
2141 * @param pVmcsInfo The VMCS info. object.
2142 * @param cMsrs The number of MSRs.
2143 */
2144static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2145{
2146 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2147 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2148 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2149 {
2150 /* Commit the MSR counts to the VMCS and update the cache. */
2151 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2152 {
2153 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2154 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2155 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2156 pVmcsInfo->cEntryMsrLoad = cMsrs;
2157 pVmcsInfo->cExitMsrStore = cMsrs;
2158 pVmcsInfo->cExitMsrLoad = cMsrs;
2159 }
2160 return VINF_SUCCESS;
2161 }
2162
2163 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2164 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2165 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2166}
2167
2168
2169/**
2170 * Adds a new (or updates the value of an existing) guest/host MSR
2171 * pair to be swapped during the world-switch as part of the
2172 * auto-load/store MSR area in the VMCS.
2173 *
2174 * @returns VBox status code.
2175 * @param pVCpu The cross context virtual CPU structure.
2176 * @param pVmxTransient The VMX-transient structure.
2177 * @param idMsr The MSR.
2178 * @param uGuestMsrValue Value of the guest MSR.
2179 * @param fSetReadWrite Whether to set the guest read/write access of this
2180 * MSR (thus not causing a VM-exit).
2181 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2182 * necessary.
2183 */
2184static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2185 bool fSetReadWrite, bool fUpdateHostMsr)
2186{
2187 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2188 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2189 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2190 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2191 uint32_t i;
2192
2193 /* Paranoia. */
2194 Assert(pGuestMsrLoad);
2195
2196 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2197
2198 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2199 for (i = 0; i < cMsrs; i++)
2200 {
2201 if (pGuestMsrLoad[i].u32Msr == idMsr)
2202 break;
2203 }
2204
2205 bool fAdded = false;
2206 if (i == cMsrs)
2207 {
2208 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2209 ++cMsrs;
2210 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2211 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2212
2213 /* Set the guest to read/write this MSR without causing VM-exits. */
2214 if ( fSetReadWrite
2215 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2216 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2217
2218 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2219 fAdded = true;
2220 }
2221
2222 /* Update the MSR value for the newly added or already existing MSR. */
2223 pGuestMsrLoad[i].u32Msr = idMsr;
2224 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2225
2226 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2227 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2228 {
2229 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2230 pGuestMsrStore[i].u32Msr = idMsr;
2231 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2232 }
2233
2234 /* Update the corresponding slot in the host MSR area. */
2235 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2236 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2237 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2238 pHostMsr[i].u32Msr = idMsr;
2239
2240 /*
2241 * Only if the caller requests to update the host MSR value AND we've newly added the
2242 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2243 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2244 *
2245 * We do this for performance reasons since reading MSRs may be quite expensive.
2246 */
2247 if (fAdded)
2248 {
2249 if (fUpdateHostMsr)
2250 {
2251 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2252 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2253 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2254 }
2255 else
2256 {
2257 /* Someone else can do the work. */
2258 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2259 }
2260 }
2261 return VINF_SUCCESS;
2262}
2263
2264
2265/**
2266 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2267 * auto-load/store MSR area in the VMCS.
2268 *
2269 * @returns VBox status code.
2270 * @param pVCpu The cross context virtual CPU structure.
2271 * @param pVmxTransient The VMX-transient structure.
2272 * @param idMsr The MSR.
2273 */
2274static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2275{
2276 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2277 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2278 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2279 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2280
2281 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2282
2283 for (uint32_t i = 0; i < cMsrs; i++)
2284 {
2285 /* Find the MSR. */
2286 if (pGuestMsrLoad[i].u32Msr == idMsr)
2287 {
2288 /*
2289 * If it's the last MSR, we only need to reduce the MSR count.
2290 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2291 */
2292 if (i < cMsrs - 1)
2293 {
2294 /* Remove it from the VM-entry MSR-load area. */
2295 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2296 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2297
2298 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2299 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2300 {
2301 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2302 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2303 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2304 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2305 }
2306
2307 /* Remove it from the VM-exit MSR-load area. */
2308 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2309 Assert(pHostMsr[i].u32Msr == idMsr);
2310 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2311 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2312 }
2313
2314 /* Reduce the count to reflect the removed MSR and bail. */
2315 --cMsrs;
2316 break;
2317 }
2318 }
2319
2320 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2321 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2322 {
2323 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2324 AssertRCReturn(rc, rc);
2325
2326 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2327 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2328 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2329
2330 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2331 return VINF_SUCCESS;
2332 }
2333
2334 return VERR_NOT_FOUND;
2335}
2336
2337
2338/**
2339 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2340 *
2341 * @returns @c true if found, @c false otherwise.
2342 * @param pVmcsInfo The VMCS info. object.
2343 * @param idMsr The MSR to find.
2344 */
2345static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2346{
2347 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2348 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2349 Assert(pMsrs);
2350 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2351 for (uint32_t i = 0; i < cMsrs; i++)
2352 {
2353 if (pMsrs[i].u32Msr == idMsr)
2354 return true;
2355 }
2356 return false;
2357}
2358
2359
2360/**
2361 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2362 *
2363 * @param pVCpu The cross context virtual CPU structure.
2364 * @param pVmcsInfo The VMCS info. object.
2365 *
2366 * @remarks No-long-jump zone!!!
2367 */
2368static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2369{
2370 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2371
2372 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2373 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2374 Assert(pHostMsrLoad);
2375 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2376 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2377 for (uint32_t i = 0; i < cMsrs; i++)
2378 {
2379 /*
2380 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2381 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2382 */
2383 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2384 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2385 else
2386 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2387 }
2388}
2389
2390
2391/**
2392 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2393 * perform lazy restoration of the host MSRs while leaving VT-x.
2394 *
2395 * @param pVCpu The cross context virtual CPU structure.
2396 *
2397 * @remarks No-long-jump zone!!!
2398 */
2399static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2400{
2401 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2402
2403 /*
2404 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2405 */
2406 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2407 {
2408 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2409 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2410 {
2411 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2412 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2413 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2414 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2415 }
2416 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2417 }
2418}
2419
2420
2421/**
2422 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2423 * lazily while leaving VT-x.
2424 *
2425 * @returns true if it does, false otherwise.
2426 * @param pVCpu The cross context virtual CPU structure.
2427 * @param idMsr The MSR to check.
2428 */
2429static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2430{
2431 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2432 {
2433 switch (idMsr)
2434 {
2435 case MSR_K8_LSTAR:
2436 case MSR_K6_STAR:
2437 case MSR_K8_SF_MASK:
2438 case MSR_K8_KERNEL_GS_BASE:
2439 return true;
2440 }
2441 }
2442 return false;
2443}
2444
2445
2446/**
2447 * Loads a set of guests MSRs to allow read/passthru to the guest.
2448 *
2449 * The name of this function is slightly confusing. This function does NOT
2450 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2451 * common prefix for functions dealing with "lazy restoration" of the shared
2452 * MSRs.
2453 *
2454 * @param pVCpu The cross context virtual CPU structure.
2455 *
2456 * @remarks No-long-jump zone!!!
2457 */
2458static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2459{
2460 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2461 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2462
2463 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2464 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2465 {
2466 /*
2467 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2468 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2469 * we can skip a few MSR writes.
2470 *
2471 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2472 * guest MSR values in the guest-CPU context might be different to what's currently
2473 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2474 * CPU, see @bugref{8728}.
2475 */
2476 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2477 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2478 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2479 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2480 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2481 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2482 {
2483#ifdef VBOX_STRICT
2484 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2485 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2486 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2487 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2488#endif
2489 }
2490 else
2491 {
2492 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2493 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2494 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2495 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2496 }
2497 }
2498 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2499}
2500
2501
2502/**
2503 * Performs lazy restoration of the set of host MSRs if they were previously
2504 * loaded with guest MSR values.
2505 *
2506 * @param pVCpu The cross context virtual CPU structure.
2507 *
2508 * @remarks No-long-jump zone!!!
2509 * @remarks The guest MSRs should have been saved back into the guest-CPU
2510 * context by hmR0VmxImportGuestState()!!!
2511 */
2512static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2513{
2514 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2515 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2516
2517 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2518 {
2519 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2520 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2521 {
2522 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2523 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2524 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2525 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2526 }
2527 }
2528 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2529}
2530
2531
2532/**
2533 * Verifies that our cached values of the VMCS fields are all consistent with
2534 * what's actually present in the VMCS.
2535 *
2536 * @returns VBox status code.
2537 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2538 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2539 * VMCS content. HMCPU error-field is
2540 * updated, see VMX_VCI_XXX.
2541 * @param pVCpu The cross context virtual CPU structure.
2542 * @param pVmcsInfo The VMCS info. object.
2543 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2544 */
2545static int hmR0VmxCheckVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2546{
2547 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2548
2549 uint32_t u32Val;
2550 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2551 AssertRC(rc);
2552 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2553 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2554 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2555 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2556
2557 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2558 AssertRC(rc);
2559 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2560 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2561 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2562 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2563
2564 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2565 AssertRC(rc);
2566 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2567 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2568 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2569 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2570
2571 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2572 AssertRC(rc);
2573 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2574 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2575 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2576 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2577
2578 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2579 {
2580 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2581 AssertRC(rc);
2582 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2583 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2584 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2585 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2586 }
2587
2588 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2589 AssertRC(rc);
2590 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2591 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2592 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2593 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2594
2595 uint64_t u64Val;
2596 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2597 AssertRC(rc);
2598 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2599 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2600 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2601 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2602
2603 NOREF(pcszVmcs);
2604 return VINF_SUCCESS;
2605}
2606
2607
2608#ifdef VBOX_STRICT
2609/**
2610 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2611 *
2612 * @param pVCpu The cross context virtual CPU structure.
2613 * @param pVmcsInfo The VMCS info. object.
2614 */
2615static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2616{
2617 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2618
2619 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2620 {
2621 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2622 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2623 uint64_t uVmcsEferMsrVmcs;
2624 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2625 AssertRC(rc);
2626
2627 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2628 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2629 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2630 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2631 }
2632}
2633
2634
2635/**
2636 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2637 * VMCS are correct.
2638 *
2639 * @param pVCpu The cross context virtual CPU structure.
2640 * @param pVmcsInfo The VMCS info. object.
2641 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2642 */
2643static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2644{
2645 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2646
2647 /* Read the various MSR-area counts from the VMCS. */
2648 uint32_t cEntryLoadMsrs;
2649 uint32_t cExitStoreMsrs;
2650 uint32_t cExitLoadMsrs;
2651 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2652 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2653 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2654
2655 /* Verify all the MSR counts are the same. */
2656 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2657 Assert(cExitStoreMsrs == cExitLoadMsrs);
2658 uint32_t const cMsrs = cExitLoadMsrs;
2659
2660 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2661 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2662
2663 /* Verify the MSR counts are within the allocated page size. */
2664 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2665
2666 /* Verify the relevant contents of the MSR areas match. */
2667 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2668 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2669 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2670 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2671 for (uint32_t i = 0; i < cMsrs; i++)
2672 {
2673 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2674 if (fSeparateExitMsrStorePage)
2675 {
2676 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2677 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2678 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2679 }
2680
2681 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2682 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2683 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2684
2685 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2686 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2687 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2688 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2689
2690 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2691 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2692 if (fIsEferMsr)
2693 {
2694 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2695 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2696 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2697 }
2698
2699 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2700 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2701 {
2702 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2703 if (fIsEferMsr)
2704 {
2705 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2706 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2707 }
2708 else
2709 {
2710 if (!fIsNstGstVmcs)
2711 {
2712 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2713 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2714 }
2715 else
2716 {
2717 /*
2718 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2719 * execute a nested-guest with MSR passthrough.
2720 *
2721 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2722 * allow passthrough too.
2723 */
2724 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2725 Assert(pvMsrBitmapNstGst);
2726 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2727 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2728 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2729 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2730 }
2731 }
2732 }
2733
2734 /* Move to the next MSR. */
2735 pHostMsrLoad++;
2736 pGuestMsrLoad++;
2737 pGuestMsrStore++;
2738 }
2739}
2740#endif /* VBOX_STRICT */
2741
2742
2743/**
2744 * Flushes the TLB using EPT.
2745 *
2746 * @returns VBox status code.
2747 * @param pVCpu The cross context virtual CPU structure of the calling
2748 * EMT. Can be NULL depending on @a enmTlbFlush.
2749 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2750 * enmTlbFlush.
2751 * @param enmTlbFlush Type of flush.
2752 *
2753 * @remarks Caller is responsible for making sure this function is called only
2754 * when NestedPaging is supported and providing @a enmTlbFlush that is
2755 * supported by the CPU.
2756 * @remarks Can be called with interrupts disabled.
2757 */
2758static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2759{
2760 uint64_t au64Descriptor[2];
2761 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2762 au64Descriptor[0] = 0;
2763 else
2764 {
2765 Assert(pVCpu);
2766 Assert(pVmcsInfo);
2767 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2768 }
2769 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2770
2771 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2772 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2773
2774 if ( RT_SUCCESS(rc)
2775 && pVCpu)
2776 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2777}
2778
2779
2780/**
2781 * Flushes the TLB using VPID.
2782 *
2783 * @returns VBox status code.
2784 * @param pVCpu The cross context virtual CPU structure of the calling
2785 * EMT. Can be NULL depending on @a enmTlbFlush.
2786 * @param enmTlbFlush Type of flush.
2787 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2788 * on @a enmTlbFlush).
2789 *
2790 * @remarks Can be called with interrupts disabled.
2791 */
2792static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2793{
2794 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2795
2796 uint64_t au64Descriptor[2];
2797 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2798 {
2799 au64Descriptor[0] = 0;
2800 au64Descriptor[1] = 0;
2801 }
2802 else
2803 {
2804 AssertPtr(pVCpu);
2805 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2806 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2807 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2808 au64Descriptor[1] = GCPtr;
2809 }
2810
2811 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2812 AssertMsg(rc == VINF_SUCCESS,
2813 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2814
2815 if ( RT_SUCCESS(rc)
2816 && pVCpu)
2817 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2818 NOREF(rc);
2819}
2820
2821
2822/**
2823 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2824 * otherwise there is nothing really to invalidate.
2825 *
2826 * @returns VBox status code.
2827 * @param pVCpu The cross context virtual CPU structure.
2828 * @param GCVirt Guest virtual address of the page to invalidate.
2829 */
2830VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2831{
2832 AssertPtr(pVCpu);
2833 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2834
2835 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2836 {
2837 /*
2838 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2839 * the EPT case. See @bugref{6043} and @bugref{6177}.
2840 *
2841 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2842 * as this function maybe called in a loop with individual addresses.
2843 */
2844 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2845 if (pVM->hm.s.vmx.fVpid)
2846 {
2847 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2848 if (fVpidFlush)
2849 {
2850 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2851 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2852 }
2853 else
2854 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2855 }
2856 else if (pVM->hm.s.fNestedPaging)
2857 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2858 }
2859
2860 return VINF_SUCCESS;
2861}
2862
2863
2864/**
2865 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2866 * case where neither EPT nor VPID is supported by the CPU.
2867 *
2868 * @param pHostCpu The HM physical-CPU structure.
2869 * @param pVCpu The cross context virtual CPU structure.
2870 *
2871 * @remarks Called with interrupts disabled.
2872 */
2873static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2874{
2875 AssertPtr(pVCpu);
2876 AssertPtr(pHostCpu);
2877
2878 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2879
2880 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2881 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2882 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2883 pVCpu->hm.s.fForceTLBFlush = false;
2884 return;
2885}
2886
2887
2888/**
2889 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2890 *
2891 * @param pHostCpu The HM physical-CPU structure.
2892 * @param pVCpu The cross context virtual CPU structure.
2893 * @param pVmcsInfo The VMCS info. object.
2894 *
2895 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2896 * nomenclature. The reason is, to avoid confusion in compare statements
2897 * since the host-CPU copies are named "ASID".
2898 *
2899 * @remarks Called with interrupts disabled.
2900 */
2901static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2902{
2903#ifdef VBOX_WITH_STATISTICS
2904 bool fTlbFlushed = false;
2905# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2906# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2907 if (!fTlbFlushed) \
2908 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2909 } while (0)
2910#else
2911# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2912# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2913#endif
2914
2915 AssertPtr(pVCpu);
2916 AssertPtr(pHostCpu);
2917 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2918
2919 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2920 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2921 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2922 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2923
2924 /*
2925 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2926 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2927 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2928 * cannot reuse the current ASID anymore.
2929 */
2930 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2931 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2932 {
2933 ++pHostCpu->uCurrentAsid;
2934 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2935 {
2936 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2937 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2938 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2939 }
2940
2941 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2942 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2943 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2944
2945 /*
2946 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2947 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2948 */
2949 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2950 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2951 HMVMX_SET_TAGGED_TLB_FLUSHED();
2952 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2953 }
2954 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2955 {
2956 /*
2957 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2958 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2959 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2960 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2961 * mappings, see @bugref{6568}.
2962 *
2963 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2964 */
2965 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2966 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2967 HMVMX_SET_TAGGED_TLB_FLUSHED();
2968 }
2969 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2970 {
2971 /*
2972 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2973 * address which requires flushing the TLB of EPT cached structures.
2974 *
2975 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2976 */
2977 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2978 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2979 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2980 HMVMX_SET_TAGGED_TLB_FLUSHED();
2981 }
2982
2983
2984 pVCpu->hm.s.fForceTLBFlush = false;
2985 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2986
2987 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2988 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2989 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2990 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2991 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2992 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2993 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2994 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2995 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2996
2997 /* Update VMCS with the VPID. */
2998 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2999 AssertRC(rc);
3000
3001#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3002}
3003
3004
3005/**
3006 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3007 *
3008 * @param pHostCpu The HM physical-CPU structure.
3009 * @param pVCpu The cross context virtual CPU structure.
3010 * @param pVmcsInfo The VMCS info. object.
3011 *
3012 * @remarks Called with interrupts disabled.
3013 */
3014static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3015{
3016 AssertPtr(pVCpu);
3017 AssertPtr(pHostCpu);
3018 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3019 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3020 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3021
3022 /*
3023 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3024 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3025 */
3026 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3027 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3028 {
3029 pVCpu->hm.s.fForceTLBFlush = true;
3030 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3031 }
3032
3033 /* Check for explicit TLB flushes. */
3034 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3035 {
3036 pVCpu->hm.s.fForceTLBFlush = true;
3037 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3038 }
3039
3040 /* Check for TLB flushes while switching to/from a nested-guest. */
3041 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3042 {
3043 pVCpu->hm.s.fForceTLBFlush = true;
3044 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3045 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3046 }
3047
3048 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3049 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3050
3051 if (pVCpu->hm.s.fForceTLBFlush)
3052 {
3053 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3054 pVCpu->hm.s.fForceTLBFlush = false;
3055 }
3056}
3057
3058
3059/**
3060 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3061 *
3062 * @param pHostCpu The HM physical-CPU structure.
3063 * @param pVCpu The cross context virtual CPU structure.
3064 *
3065 * @remarks Called with interrupts disabled.
3066 */
3067static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3068{
3069 AssertPtr(pVCpu);
3070 AssertPtr(pHostCpu);
3071 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3072 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3073 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3074
3075 /*
3076 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3077 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3078 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3079 * cannot reuse the current ASID anymore.
3080 */
3081 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3082 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3083 {
3084 pVCpu->hm.s.fForceTLBFlush = true;
3085 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3086 }
3087
3088 /* Check for explicit TLB flushes. */
3089 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3090 {
3091 /*
3092 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3093 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3094 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3095 * include fExplicitFlush's too) - an obscure corner case.
3096 */
3097 pVCpu->hm.s.fForceTLBFlush = true;
3098 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3099 }
3100
3101 /* Check for TLB flushes while switching to/from a nested-guest. */
3102 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3103 {
3104 pVCpu->hm.s.fForceTLBFlush = true;
3105 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3106 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3107 }
3108
3109 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3110 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3111 if (pVCpu->hm.s.fForceTLBFlush)
3112 {
3113 ++pHostCpu->uCurrentAsid;
3114 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3115 {
3116 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3117 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3118 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3119 }
3120
3121 pVCpu->hm.s.fForceTLBFlush = false;
3122 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3123 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3124 if (pHostCpu->fFlushAsidBeforeUse)
3125 {
3126 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3127 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3128 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3129 {
3130 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3131 pHostCpu->fFlushAsidBeforeUse = false;
3132 }
3133 else
3134 {
3135 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3136 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3137 }
3138 }
3139 }
3140
3141 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3142 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3143 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3144 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3145 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3146 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3147 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3148
3149 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3150 AssertRC(rc);
3151}
3152
3153
3154/**
3155 * Flushes the guest TLB entry based on CPU capabilities.
3156 *
3157 * @param pHostCpu The HM physical-CPU structure.
3158 * @param pVCpu The cross context virtual CPU structure.
3159 * @param pVmcsInfo The VMCS info. object.
3160 *
3161 * @remarks Called with interrupts disabled.
3162 */
3163static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3164{
3165#ifdef HMVMX_ALWAYS_FLUSH_TLB
3166 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3167#endif
3168 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3169 switch (pVM->hm.s.vmx.enmTlbFlushType)
3170 {
3171 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3172 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3173 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3174 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3175 default:
3176 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3177 break;
3178 }
3179 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3180}
3181
3182
3183/**
3184 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3185 * TLB entries from the host TLB before VM-entry.
3186 *
3187 * @returns VBox status code.
3188 * @param pVM The cross context VM structure.
3189 */
3190static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3191{
3192 /*
3193 * Determine optimal flush type for nested paging.
3194 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3195 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3196 */
3197 if (pVM->hm.s.fNestedPaging)
3198 {
3199 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3200 {
3201 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3202 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3203 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3204 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3205 else
3206 {
3207 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3208 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3209 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3210 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3211 }
3212
3213 /* Make sure the write-back cacheable memory type for EPT is supported. */
3214 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3215 {
3216 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3217 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3218 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3219 }
3220
3221 /* EPT requires a page-walk length of 4. */
3222 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3223 {
3224 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3225 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3226 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3227 }
3228 }
3229 else
3230 {
3231 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3232 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3233 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3234 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3235 }
3236 }
3237
3238 /*
3239 * Determine optimal flush type for VPID.
3240 */
3241 if (pVM->hm.s.vmx.fVpid)
3242 {
3243 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3244 {
3245 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3246 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3247 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3248 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3249 else
3250 {
3251 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3252 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3253 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3254 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3255 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3256 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3257 pVM->hm.s.vmx.fVpid = false;
3258 }
3259 }
3260 else
3261 {
3262 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3263 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3264 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3265 pVM->hm.s.vmx.fVpid = false;
3266 }
3267 }
3268
3269 /*
3270 * Setup the handler for flushing tagged-TLBs.
3271 */
3272 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3273 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3274 else if (pVM->hm.s.fNestedPaging)
3275 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3276 else if (pVM->hm.s.vmx.fVpid)
3277 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3278 else
3279 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3280 return VINF_SUCCESS;
3281}
3282
3283
3284#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3285/**
3286 * Sets up the shadow VMCS fields arrays.
3287 *
3288 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3289 * executing the guest.
3290 *
3291 * @returns VBox status code.
3292 * @param pVM The cross context VM structure.
3293 */
3294static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3295{
3296 /*
3297 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3298 * when the host does not support it.
3299 */
3300 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3301 if ( !fGstVmwriteAll
3302 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3303 { /* likely. */ }
3304 else
3305 {
3306 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3307 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3308 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3309 }
3310
3311 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3312 uint32_t cRwFields = 0;
3313 uint32_t cRoFields = 0;
3314 for (uint32_t i = 0; i < cVmcsFields; i++)
3315 {
3316 VMXVMCSFIELD VmcsField;
3317 VmcsField.u = g_aVmcsFields[i];
3318
3319 /*
3320 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3321 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3322 * in the shadow VMCS fields array as they would be redundant.
3323 *
3324 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3325 * we must not include it in the shadow VMCS fields array. Guests attempting to
3326 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3327 * the required behavior.
3328 */
3329 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3330 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3331 {
3332 /*
3333 * Read-only fields are placed in a separate array so that while syncing shadow
3334 * VMCS fields later (which is more performance critical) we can avoid branches.
3335 *
3336 * However, if the guest can write to all fields (including read-only fields),
3337 * we treat it a as read/write field. Otherwise, writing to these fields would
3338 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3339 */
3340 if ( fGstVmwriteAll
3341 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3342 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3343 else
3344 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3345 }
3346 }
3347
3348 /* Update the counts. */
3349 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3350 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3351 return VINF_SUCCESS;
3352}
3353
3354
3355/**
3356 * Sets up the VMREAD and VMWRITE bitmaps.
3357 *
3358 * @param pVM The cross context VM structure.
3359 */
3360static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3361{
3362 /*
3363 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3364 */
3365 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3366 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3367 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3368 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3369 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3370
3371 /*
3372 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3373 * VMREAD and VMWRITE bitmaps.
3374 */
3375 {
3376 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3377 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3378 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3379 {
3380 uint32_t const uVmcsField = paShadowVmcsFields[i];
3381 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3382 Assert(uVmcsField >> 3 < cbBitmap);
3383 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3384 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3385 }
3386 }
3387
3388 /*
3389 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3390 * if the host supports VMWRITE to all supported VMCS fields.
3391 */
3392 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3393 {
3394 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3395 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3396 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3397 {
3398 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3399 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3400 Assert(uVmcsField >> 3 < cbBitmap);
3401 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3402 }
3403 }
3404}
3405#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3406
3407
3408/**
3409 * Sets up the virtual-APIC page address for the VMCS.
3410 *
3411 * @param pVmcsInfo The VMCS info. object.
3412 */
3413DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3414{
3415 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3416 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3417 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3418 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3419 AssertRC(rc);
3420}
3421
3422
3423/**
3424 * Sets up the MSR-bitmap address for the VMCS.
3425 *
3426 * @param pVmcsInfo The VMCS info. object.
3427 */
3428DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3429{
3430 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3431 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3432 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3433 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3434 AssertRC(rc);
3435}
3436
3437
3438/**
3439 * Sets up the APIC-access page address for the VMCS.
3440 *
3441 * @param pVCpu The cross context virtual CPU structure.
3442 */
3443DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3444{
3445 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3446 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3447 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3448 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3449 AssertRC(rc);
3450}
3451
3452
3453#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3454/**
3455 * Sets up the VMREAD bitmap address for the VMCS.
3456 *
3457 * @param pVCpu The cross context virtual CPU structure.
3458 */
3459DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3460{
3461 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3462 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3463 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3464 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3465 AssertRC(rc);
3466}
3467
3468
3469/**
3470 * Sets up the VMWRITE bitmap address for the VMCS.
3471 *
3472 * @param pVCpu The cross context virtual CPU structure.
3473 */
3474DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3475{
3476 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3477 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3478 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3479 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3480 AssertRC(rc);
3481}
3482#endif
3483
3484
3485/**
3486 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3487 * in the VMCS.
3488 *
3489 * @returns VBox status code.
3490 * @param pVmcsInfo The VMCS info. object.
3491 */
3492DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3493{
3494 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3495 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3496 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3497
3498 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3499 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3500 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3501
3502 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3503 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3504 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3505
3506 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3507 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3508 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3509 return VINF_SUCCESS;
3510}
3511
3512
3513/**
3514 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3515 *
3516 * @param pVCpu The cross context virtual CPU structure.
3517 * @param pVmcsInfo The VMCS info. object.
3518 */
3519static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3520{
3521 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3522
3523 /*
3524 * The guest can access the following MSRs (read, write) without causing
3525 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3526 */
3527 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3528 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3529 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3530 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3531 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3532 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3533
3534 /*
3535 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3536 * associated with then. We never need to intercept access (writes need to be
3537 * executed without causing a VM-exit, reads will #GP fault anyway).
3538 *
3539 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3540 * read/write them. We swap the the guest/host MSR value using the
3541 * auto-load/store MSR area.
3542 */
3543 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3544 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3545 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3546 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3547 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3548 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3549
3550 /*
3551 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3552 * required for 64-bit guests.
3553 */
3554 if (pVM->hm.s.fAllow64BitGuests)
3555 {
3556 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3557 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3558 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3559 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3560 }
3561
3562 /*
3563 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3564 */
3565#ifdef VBOX_STRICT
3566 Assert(pVmcsInfo->pvMsrBitmap);
3567 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3568 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3569#endif
3570}
3571
3572
3573/**
3574 * Sets up pin-based VM-execution controls in the VMCS.
3575 *
3576 * @returns VBox status code.
3577 * @param pVCpu The cross context virtual CPU structure.
3578 * @param pVmcsInfo The VMCS info. object.
3579 */
3580static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3581{
3582 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3583 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3584 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3585
3586 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3587 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3588
3589 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3590 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3591
3592 /* Enable the VMX-preemption timer. */
3593 if (pVM->hm.s.vmx.fUsePreemptTimer)
3594 {
3595 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3596 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3597 }
3598
3599#if 0
3600 /* Enable posted-interrupt processing. */
3601 if (pVM->hm.s.fPostedIntrs)
3602 {
3603 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3604 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3605 fVal |= VMX_PIN_CTLS_POSTED_INT;
3606 }
3607#endif
3608
3609 if ((fVal & fZap) != fVal)
3610 {
3611 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3612 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3613 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3614 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3615 }
3616
3617 /* Commit it to the VMCS and update our cache. */
3618 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3619 AssertRC(rc);
3620 pVmcsInfo->u32PinCtls = fVal;
3621
3622 return VINF_SUCCESS;
3623}
3624
3625
3626/**
3627 * Sets up secondary processor-based VM-execution controls in the VMCS.
3628 *
3629 * @returns VBox status code.
3630 * @param pVCpu The cross context virtual CPU structure.
3631 * @param pVmcsInfo The VMCS info. object.
3632 */
3633static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3634{
3635 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3636 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3637 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3638
3639 /* WBINVD causes a VM-exit. */
3640 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3641 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3642
3643 /* Enable EPT (aka nested-paging). */
3644 if (pVM->hm.s.fNestedPaging)
3645 fVal |= VMX_PROC_CTLS2_EPT;
3646
3647 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3648 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3649 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3650 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3651 fVal |= VMX_PROC_CTLS2_INVPCID;
3652
3653 /* Enable VPID. */
3654 if (pVM->hm.s.vmx.fVpid)
3655 fVal |= VMX_PROC_CTLS2_VPID;
3656
3657 /* Enable unrestricted guest execution. */
3658 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3659 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3660
3661#if 0
3662 if (pVM->hm.s.fVirtApicRegs)
3663 {
3664 /* Enable APIC-register virtualization. */
3665 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3666 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3667
3668 /* Enable virtual-interrupt delivery. */
3669 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3670 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3671 }
3672#endif
3673
3674 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3675 where the TPR shadow resides. */
3676 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3677 * done dynamically. */
3678 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3679 {
3680 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3681 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3682 }
3683
3684 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3685 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3686 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3687 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3688 fVal |= VMX_PROC_CTLS2_RDTSCP;
3689
3690 /* Enable Pause-Loop exiting. */
3691 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3692 && pVM->hm.s.vmx.cPleGapTicks
3693 && pVM->hm.s.vmx.cPleWindowTicks)
3694 {
3695 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3696
3697 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3698 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3699 }
3700
3701 if ((fVal & fZap) != fVal)
3702 {
3703 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3704 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3705 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3706 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3707 }
3708
3709 /* Commit it to the VMCS and update our cache. */
3710 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3711 AssertRC(rc);
3712 pVmcsInfo->u32ProcCtls2 = fVal;
3713
3714 return VINF_SUCCESS;
3715}
3716
3717
3718/**
3719 * Sets up processor-based VM-execution controls in the VMCS.
3720 *
3721 * @returns VBox status code.
3722 * @param pVCpu The cross context virtual CPU structure.
3723 * @param pVmcsInfo The VMCS info. object.
3724 */
3725static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3726{
3727 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3728
3729 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3730 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3731
3732 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3733 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3734 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3735 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3736 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3737 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3738 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3739
3740 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3741 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3742 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3743 {
3744 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3745 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3746 }
3747
3748 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3749 if (!pVM->hm.s.fNestedPaging)
3750 {
3751 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3752 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3753 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3754 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3755 }
3756
3757 /* Use TPR shadowing if supported by the CPU. */
3758 if ( PDMHasApic(pVM)
3759 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3760 {
3761 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3762 /* CR8 writes cause a VM-exit based on TPR threshold. */
3763 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3764 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3765 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3766 }
3767 else
3768 {
3769 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3770 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3771 if (pVM->hm.s.fAllow64BitGuests)
3772 {
3773 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3774 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3775 }
3776 }
3777
3778 /* Use MSR-bitmaps if supported by the CPU. */
3779 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3780 {
3781 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3782 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3783 }
3784
3785 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3786 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3787 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3788
3789 if ((fVal & fZap) != fVal)
3790 {
3791 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3792 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3793 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3794 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3795 }
3796
3797 /* Commit it to the VMCS and update our cache. */
3798 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3799 AssertRC(rc);
3800 pVmcsInfo->u32ProcCtls = fVal;
3801
3802 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3803 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3804 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3805
3806 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3807 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3808 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3809
3810 /* Sanity check, should not really happen. */
3811 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3812 { /* likely */ }
3813 else
3814 {
3815 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3816 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3817 }
3818
3819 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3820 return VINF_SUCCESS;
3821}
3822
3823
3824/**
3825 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3826 * Processor-based VM-execution) control fields in the VMCS.
3827 *
3828 * @returns VBox status code.
3829 * @param pVCpu The cross context virtual CPU structure.
3830 * @param pVmcsInfo The VMCS info. object.
3831 */
3832static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3833{
3834#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3835 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3836 {
3837 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3838 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3839 }
3840#endif
3841
3842 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3843 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3844 AssertRC(rc);
3845
3846 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3847 if (RT_SUCCESS(rc))
3848 {
3849 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3850 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3851
3852 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3853 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3854
3855 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3856 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3857 return VINF_SUCCESS;
3858 }
3859 else
3860 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3861 return rc;
3862}
3863
3864
3865/**
3866 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3867 *
3868 * We shall setup those exception intercepts that don't change during the
3869 * lifetime of the VM here. The rest are done dynamically while loading the
3870 * guest state.
3871 *
3872 * @param pVCpu The cross context virtual CPU structure.
3873 * @param pVmcsInfo The VMCS info. object.
3874 */
3875static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3876{
3877 /*
3878 * The following exceptions are always intercepted:
3879 *
3880 * #AC - To prevent the guest from hanging the CPU.
3881 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3882 * recursive #DBs can cause a CPU hang.
3883 * #PF - To sync our shadow page tables when nested-paging is not used.
3884 */
3885 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3886 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3887 | RT_BIT(X86_XCPT_DB)
3888 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3889
3890 /* Commit it to the VMCS. */
3891 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3892 AssertRC(rc);
3893
3894 /* Update our cache of the exception bitmap. */
3895 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3896}
3897
3898
3899#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3900/**
3901 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3902 *
3903 * @returns VBox status code.
3904 * @param pVCpu The cross context virtual CPU structure.
3905 * @param pVmcsInfo The VMCS info. object.
3906 */
3907static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3908{
3909 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3910 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3911 AssertRC(rc);
3912
3913 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3914 if (RT_SUCCESS(rc))
3915 {
3916 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3917 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3918
3919 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
3920 Assert(!pVmcsInfo->u64Cr0Mask);
3921 Assert(!pVmcsInfo->u64Cr4Mask);
3922 return VINF_SUCCESS;
3923 }
3924 else
3925 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3926 return rc;
3927}
3928#endif
3929
3930
3931/**
3932 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3933 * VMX.
3934 *
3935 * @returns VBox status code.
3936 * @param pVCpu The cross context virtual CPU structure.
3937 * @param pVmcsInfo The VMCS info. object.
3938 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3939 */
3940static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3941{
3942 Assert(pVmcsInfo->pvVmcs);
3943 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3944
3945 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3946 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3947 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3948 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3949
3950 LogFlowFunc(("\n"));
3951
3952 /*
3953 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3954 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3955 */
3956 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3957 if (RT_SUCCESS(rc))
3958 {
3959 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3960 if (RT_SUCCESS(rc))
3961 {
3962 if (!fIsNstGstVmcs)
3963 {
3964 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3965 if (RT_SUCCESS(rc))
3966 {
3967 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3968 if (RT_SUCCESS(rc))
3969 {
3970 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3971 if (RT_SUCCESS(rc))
3972 {
3973 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3974#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3975 /*
3976 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3977 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3978 * making it fit for use when VMCS shadowing is later enabled.
3979 */
3980 if (pVmcsInfo->pvShadowVmcs)
3981 {
3982 VMXVMCSREVID VmcsRevId;
3983 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3984 VmcsRevId.n.fIsShadowVmcs = 1;
3985 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
3986 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
3987 if (RT_SUCCESS(rc))
3988 { /* likely */ }
3989 else
3990 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
3991 }
3992#endif
3993 }
3994 else
3995 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
3996 }
3997 else
3998 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
3999 }
4000 else
4001 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4002 }
4003 else
4004 {
4005#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4006 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4007 if (RT_SUCCESS(rc))
4008 { /* likely */ }
4009 else
4010 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4011#else
4012 AssertFailed();
4013#endif
4014 }
4015 }
4016 else
4017 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4018 }
4019 else
4020 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4021
4022 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4023 if (RT_SUCCESS(rc))
4024 {
4025 rc = hmR0VmxClearVmcs(pVmcsInfo);
4026 if (RT_SUCCESS(rc))
4027 { /* likely */ }
4028 else
4029 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4030 }
4031
4032 /*
4033 * Update the last-error record both for failures and success, so we
4034 * can propagate the status code back to ring-3 for diagnostics.
4035 */
4036 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4037 NOREF(pszVmcs);
4038 return rc;
4039}
4040
4041
4042/**
4043 * Does global VT-x initialization (called during module initialization).
4044 *
4045 * @returns VBox status code.
4046 */
4047VMMR0DECL(int) VMXR0GlobalInit(void)
4048{
4049#ifdef HMVMX_USE_FUNCTION_TABLE
4050 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4051# ifdef VBOX_STRICT
4052 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4053 Assert(g_apfnVMExitHandlers[i]);
4054# endif
4055#endif
4056 return VINF_SUCCESS;
4057}
4058
4059
4060/**
4061 * Does global VT-x termination (called during module termination).
4062 */
4063VMMR0DECL(void) VMXR0GlobalTerm()
4064{
4065 /* Nothing to do currently. */
4066}
4067
4068
4069/**
4070 * Sets up and activates VT-x on the current CPU.
4071 *
4072 * @returns VBox status code.
4073 * @param pHostCpu The HM physical-CPU structure.
4074 * @param pVM The cross context VM structure. Can be
4075 * NULL after a host resume operation.
4076 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4077 * fEnabledByHost is @c true).
4078 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4079 * @a fEnabledByHost is @c true).
4080 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4081 * enable VT-x on the host.
4082 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4083 */
4084VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4085 PCSUPHWVIRTMSRS pHwvirtMsrs)
4086{
4087 AssertPtr(pHostCpu);
4088 AssertPtr(pHwvirtMsrs);
4089 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4090
4091 /* Enable VT-x if it's not already enabled by the host. */
4092 if (!fEnabledByHost)
4093 {
4094 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4095 if (RT_FAILURE(rc))
4096 return rc;
4097 }
4098
4099 /*
4100 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4101 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4102 * invalidated when flushing by VPID.
4103 */
4104 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4105 {
4106 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4107 pHostCpu->fFlushAsidBeforeUse = false;
4108 }
4109 else
4110 pHostCpu->fFlushAsidBeforeUse = true;
4111
4112 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4113 ++pHostCpu->cTlbFlushes;
4114
4115 return VINF_SUCCESS;
4116}
4117
4118
4119/**
4120 * Deactivates VT-x on the current CPU.
4121 *
4122 * @returns VBox status code.
4123 * @param pvCpuPage Pointer to the VMXON region.
4124 * @param HCPhysCpuPage Physical address of the VMXON region.
4125 *
4126 * @remarks This function should never be called when SUPR0EnableVTx() or
4127 * similar was used to enable VT-x on the host.
4128 */
4129VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4130{
4131 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4132
4133 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4134 return hmR0VmxLeaveRootMode();
4135}
4136
4137
4138/**
4139 * Does per-VM VT-x initialization.
4140 *
4141 * @returns VBox status code.
4142 * @param pVM The cross context VM structure.
4143 */
4144VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4145{
4146 AssertPtr(pVM);
4147 LogFlowFunc(("pVM=%p\n", pVM));
4148
4149 int rc = hmR0VmxStructsAlloc(pVM);
4150 if (RT_FAILURE(rc))
4151 {
4152 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4153 return rc;
4154 }
4155
4156 return VINF_SUCCESS;
4157}
4158
4159
4160/**
4161 * Does per-VM VT-x termination.
4162 *
4163 * @returns VBox status code.
4164 * @param pVM The cross context VM structure.
4165 */
4166VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4167{
4168 AssertPtr(pVM);
4169 LogFlowFunc(("pVM=%p\n", pVM));
4170
4171#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4172 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4173 {
4174 Assert(pVM->hm.s.vmx.pvScratch);
4175 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4176 }
4177#endif
4178 hmR0VmxStructsFree(pVM);
4179 return VINF_SUCCESS;
4180}
4181
4182
4183/**
4184 * Sets up the VM for execution using hardware-assisted VMX.
4185 * This function is only called once per-VM during initialization.
4186 *
4187 * @returns VBox status code.
4188 * @param pVM The cross context VM structure.
4189 */
4190VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4191{
4192 AssertPtr(pVM);
4193 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4194
4195 LogFlowFunc(("pVM=%p\n", pVM));
4196
4197 /*
4198 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4199 * without causing a #GP.
4200 */
4201 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4202 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4203 { /* likely */ }
4204 else
4205 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4206
4207 /*
4208 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4209 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4210 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4211 */
4212 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4213 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4214 || !pVM->hm.s.vmx.pRealModeTSS))
4215 {
4216 LogRelFunc(("Invalid real-on-v86 state.\n"));
4217 return VERR_INTERNAL_ERROR;
4218 }
4219
4220 /* Initialize these always, see hmR3InitFinalizeR0().*/
4221 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4222 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4223
4224 /* Setup the tagged-TLB flush handlers. */
4225 int rc = hmR0VmxSetupTaggedTlb(pVM);
4226 if (RT_FAILURE(rc))
4227 {
4228 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4229 return rc;
4230 }
4231
4232#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4233 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4234 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4235 {
4236 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4237 if (RT_SUCCESS(rc))
4238 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4239 else
4240 {
4241 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4242 return rc;
4243 }
4244 }
4245#endif
4246
4247 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4248 {
4249 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4250 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4251
4252 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4253 if (RT_SUCCESS(rc))
4254 {
4255#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4256 if (pVM->cpum.ro.GuestFeatures.fVmx)
4257 {
4258 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4259 if (RT_SUCCESS(rc))
4260 { /* likely */ }
4261 else
4262 {
4263 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4264 return rc;
4265 }
4266 }
4267#endif
4268 }
4269 else
4270 {
4271 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4272 return rc;
4273 }
4274 }
4275
4276 return VINF_SUCCESS;
4277}
4278
4279
4280/**
4281 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4282 * the VMCS.
4283 */
4284static void hmR0VmxExportHostControlRegs(void)
4285{
4286 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4287 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4288 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4289}
4290
4291
4292/**
4293 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4294 * the host-state area in the VMCS.
4295 *
4296 * @returns VBox status code.
4297 * @param pVCpu The cross context virtual CPU structure.
4298 */
4299static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4300{
4301/**
4302 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4303 * requirements. See hmR0VmxExportHostSegmentRegs().
4304 */
4305#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4306 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4307 { \
4308 bool fValidSelector = true; \
4309 if ((a_selValue) & X86_SEL_LDT) \
4310 { \
4311 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4312 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4313 } \
4314 if (fValidSelector) \
4315 { \
4316 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4317 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4318 } \
4319 (a_selValue) = 0; \
4320 }
4321
4322 /*
4323 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4324 * will be messed up. We should -not- save the messed up state without restoring
4325 * the original host-state, see @bugref{7240}.
4326 *
4327 * This apparently can happen (most likely the FPU changes), deal with it rather than
4328 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4329 */
4330 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4331 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4332 {
4333 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4334 pVCpu->idCpu));
4335 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4336 }
4337 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4338
4339 /*
4340 * Host segment registers.
4341 */
4342 RTSEL uSelES = ASMGetES();
4343 RTSEL uSelCS = ASMGetCS();
4344 RTSEL uSelSS = ASMGetSS();
4345 RTSEL uSelDS = ASMGetDS();
4346 RTSEL uSelFS = ASMGetFS();
4347 RTSEL uSelGS = ASMGetGS();
4348 RTSEL uSelTR = ASMGetTR();
4349
4350 /*
4351 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4352 * gain VM-entry and restore them before we get preempted.
4353 *
4354 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4355 */
4356 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4357 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4358 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4359 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4360
4361 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4362 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4363 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4364 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4365 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4366 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4367 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4368 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4369 Assert(uSelCS);
4370 Assert(uSelTR);
4371
4372 /* Write these host selector fields into the host-state area in the VMCS. */
4373 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4374 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4375 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4376 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4377 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4378 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4379 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4380
4381 /*
4382 * Host GDTR and IDTR.
4383 */
4384 RTGDTR Gdtr;
4385 RTIDTR Idtr;
4386 RT_ZERO(Gdtr);
4387 RT_ZERO(Idtr);
4388 ASMGetGDTR(&Gdtr);
4389 ASMGetIDTR(&Idtr);
4390 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4391 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4392
4393 /*
4394 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4395 * them to the maximum limit (0xffff) on every VM-exit.
4396 */
4397 if (Gdtr.cbGdt != 0xffff)
4398 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4399
4400 /*
4401 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4402 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4403 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4404 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4405 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4406 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4407 * at 0xffff on hosts where we are sure it won't cause trouble.
4408 */
4409#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4410 if (Idtr.cbIdt < 0x0fff)
4411#else
4412 if (Idtr.cbIdt != 0xffff)
4413#endif
4414 {
4415 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4416 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4417 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4418 }
4419
4420 /*
4421 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4422 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4423 * RPL should be too in most cases.
4424 */
4425 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4426 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4427
4428 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4429 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4430
4431 /*
4432 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4433 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4434 * restoration if the host has something else. Task switching is not supported in 64-bit
4435 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4436 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4437 *
4438 * [1] See Intel spec. 3.5 "System Descriptor Types".
4439 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4440 */
4441 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4442 Assert(pDesc->System.u4Type == 11);
4443 if ( pDesc->System.u16LimitLow != 0x67
4444 || pDesc->System.u4LimitHigh)
4445 {
4446 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4447 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4448 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4449 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4450 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4451 }
4452
4453 /*
4454 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4455 */
4456 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4457 {
4458 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4459 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4460 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4461 {
4462 /* The GDT is read-only but the writable GDT is available. */
4463 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4464 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4465 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4466 AssertRCReturn(rc, rc);
4467 }
4468 }
4469
4470 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4471 AssertRC(rc);
4472
4473 /*
4474 * Host FS base and GS base.
4475 */
4476 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4477 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4478 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4479 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4480
4481 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4482 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4483 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4484 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4485 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4486
4487 return VINF_SUCCESS;
4488#undef VMXLOCAL_ADJUST_HOST_SEG
4489}
4490
4491
4492/**
4493 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4494 * host-state area of the VMCS.
4495 *
4496 * These MSRs will be automatically restored on the host after every successful
4497 * VM-exit.
4498 *
4499 * @param pVCpu The cross context virtual CPU structure.
4500 *
4501 * @remarks No-long-jump zone!!!
4502 */
4503static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4504{
4505 AssertPtr(pVCpu);
4506
4507 /*
4508 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4509 * rather than swapping them on every VM-entry.
4510 */
4511 hmR0VmxLazySaveHostMsrs(pVCpu);
4512
4513 /*
4514 * Host Sysenter MSRs.
4515 */
4516 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4517 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4518 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4519
4520 /*
4521 * Host EFER MSR.
4522 *
4523 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4524 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4525 */
4526 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4527 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4528 {
4529 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4530 AssertRC(rc);
4531 }
4532
4533 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4534 * hmR0VmxExportGuestEntryExitCtls(). */
4535}
4536
4537
4538/**
4539 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4540 *
4541 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4542 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4543 *
4544 * @returns true if we need to load guest EFER, false otherwise.
4545 * @param pVCpu The cross context virtual CPU structure.
4546 * @param pVmxTransient The VMX-transient structure.
4547 *
4548 * @remarks Requires EFER, CR4.
4549 * @remarks No-long-jump zone!!!
4550 */
4551static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4552{
4553#ifdef HMVMX_ALWAYS_SWAP_EFER
4554 RT_NOREF2(pVCpu, pVmxTransient);
4555 return true;
4556#else
4557 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4558 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4559 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4560 uint64_t const u64GuestEfer = pCtx->msrEFER;
4561
4562# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4563 /*
4564 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4565 * the nested-guest.
4566 */
4567 if ( pVmxTransient->fIsNestedGuest
4568 && ( CPUMIsGuestVmxEntryCtlsSet(pVCpu, pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4569 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4570 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4571 return true;
4572# else
4573 RT_NOREF(pVmxTransient);
4574#endif
4575
4576 /*
4577 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4578 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4579 */
4580 if ( CPUMIsGuestInLongModeEx(pCtx)
4581 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4582 return true;
4583
4584 /*
4585 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4586 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4587 *
4588 * See Intel spec. 4.5 "IA-32e Paging".
4589 * See Intel spec. 4.1.1 "Three Paging Modes".
4590 *
4591 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4592 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4593 */
4594 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4595 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4596 if ( (pCtx->cr4 & X86_CR4_PAE)
4597 && (pCtx->cr0 & X86_CR0_PG))
4598 {
4599 /*
4600 * If nested paging is not used, verify that the guest paging mode matches the
4601 * shadow paging mode which is/will be placed in the VMCS (which is what will
4602 * actually be used while executing the guest and not the CR4 shadow value).
4603 */
4604 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4605 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4606 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4607 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4608 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4609 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4610 {
4611 /* Verify that the host is NX capable. */
4612 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4613 return true;
4614 }
4615 }
4616
4617 return false;
4618#endif
4619}
4620
4621
4622/**
4623 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4624 * VMCS.
4625 *
4626 * This is typically required when the guest changes paging mode.
4627 *
4628 * @returns VBox status code.
4629 * @param pVCpu The cross context virtual CPU structure.
4630 * @param pVmxTransient The VMX-transient structure.
4631 *
4632 * @remarks Requires EFER.
4633 * @remarks No-long-jump zone!!!
4634 */
4635static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4636{
4637 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4638 {
4639 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4640 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4641
4642 /*
4643 * VM-entry controls.
4644 */
4645 {
4646 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4647 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4648
4649 /*
4650 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4651 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4652 *
4653 * For nested-guests, this is a mandatory VM-entry control. It's also
4654 * required because we do not want to leak host bits to the nested-guest.
4655 */
4656 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4657
4658 /*
4659 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4660 *
4661 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4662 * required to get the nested-guest working with hardware-assisted VMX execution.
4663 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4664 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4665 * here rather than while merging the guest VMCS controls.
4666 */
4667 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4668 {
4669 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4670 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4671 }
4672 else
4673 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4674
4675 /*
4676 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4677 *
4678 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4679 * regardless of whether the nested-guest VMCS specifies it because we are free to
4680 * load whatever MSRs we require and we do not need to modify the guest visible copy
4681 * of the VM-entry MSR load area.
4682 */
4683 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4684 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4685 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4686 else
4687 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4688
4689 /*
4690 * The following should -not- be set (since we're not in SMM mode):
4691 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4692 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4693 */
4694
4695 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4696 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4697
4698 if ((fVal & fZap) == fVal)
4699 { /* likely */ }
4700 else
4701 {
4702 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4703 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4704 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4705 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4706 }
4707
4708 /* Commit it to the VMCS. */
4709 if (pVmcsInfo->u32EntryCtls != fVal)
4710 {
4711 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4712 AssertRC(rc);
4713 pVmcsInfo->u32EntryCtls = fVal;
4714 }
4715 }
4716
4717 /*
4718 * VM-exit controls.
4719 */
4720 {
4721 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4722 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4723
4724 /*
4725 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4726 * supported the 1-setting of this bit.
4727 *
4728 * For nested-guests, we set the "save debug controls" as the converse
4729 * "load debug controls" is mandatory for nested-guests anyway.
4730 */
4731 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4732
4733 /*
4734 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4735 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4736 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4737 * hmR0VmxExportHostMsrs().
4738 *
4739 * For nested-guests, we always set this bit as we do not support 32-bit
4740 * hosts.
4741 */
4742 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4743
4744 /*
4745 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4746 *
4747 * For nested-guests, we should use the "save IA32_EFER" control if we also
4748 * used the "load IA32_EFER" control while exporting VM-entry controls.
4749 */
4750 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4751 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4752 {
4753 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4754 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4755 }
4756
4757 /*
4758 * Enable saving of the VMX-preemption timer value on VM-exit.
4759 * For nested-guests, currently not exposed/used.
4760 */
4761 if ( pVM->hm.s.vmx.fUsePreemptTimer
4762 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4763 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4764
4765 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4766 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4767
4768 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4769 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4770 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4771
4772 if ((fVal & fZap) == fVal)
4773 { /* likely */ }
4774 else
4775 {
4776 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4777 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4778 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4779 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4780 }
4781
4782 /* Commit it to the VMCS. */
4783 if (pVmcsInfo->u32ExitCtls != fVal)
4784 {
4785 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4786 AssertRC(rc);
4787 pVmcsInfo->u32ExitCtls = fVal;
4788 }
4789 }
4790
4791 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4792 }
4793 return VINF_SUCCESS;
4794}
4795
4796
4797/**
4798 * Sets the TPR threshold in the VMCS.
4799 *
4800 * @param pVmcsInfo The VMCS info. object.
4801 * @param u32TprThreshold The TPR threshold (task-priority class only).
4802 */
4803DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4804{
4805 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4806 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4807 RT_NOREF(pVmcsInfo);
4808 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4809 AssertRC(rc);
4810}
4811
4812
4813/**
4814 * Exports the guest APIC TPR state into the VMCS.
4815 *
4816 * @returns VBox status code.
4817 * @param pVCpu The cross context virtual CPU structure.
4818 * @param pVmxTransient The VMX-transient structure.
4819 *
4820 * @remarks No-long-jump zone!!!
4821 */
4822static int hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4823{
4824 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4825 {
4826 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4827
4828 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4829 if (!pVmxTransient->fIsNestedGuest)
4830 {
4831 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4832 && APICIsEnabled(pVCpu))
4833 {
4834 /*
4835 * Setup TPR shadowing.
4836 */
4837 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4838 {
4839 bool fPendingIntr = false;
4840 uint8_t u8Tpr = 0;
4841 uint8_t u8PendingIntr = 0;
4842 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4843 AssertRCReturn(rc, rc);
4844
4845 /*
4846 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4847 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4848 * priority of the pending interrupt so we can deliver the interrupt. If there
4849 * are no interrupts pending, set threshold to 0 to not cause any
4850 * TPR-below-threshold VM-exits.
4851 */
4852 uint32_t u32TprThreshold = 0;
4853 if (fPendingIntr)
4854 {
4855 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4856 (which is the Task-Priority Class). */
4857 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4858 const uint8_t u8TprPriority = u8Tpr >> 4;
4859 if (u8PendingPriority <= u8TprPriority)
4860 u32TprThreshold = u8PendingPriority;
4861 }
4862
4863 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4864 }
4865 }
4866 }
4867 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4868 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4869 }
4870 return VINF_SUCCESS;
4871}
4872
4873
4874/**
4875 * Gets the guest interruptibility-state.
4876 *
4877 * @returns Guest's interruptibility-state.
4878 * @param pVCpu The cross context virtual CPU structure.
4879 * @param pVmxTransient The VMX-transient structure.
4880 *
4881 * @remarks No-long-jump zone!!!
4882 */
4883static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4884{
4885 /*
4886 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4887 */
4888 uint32_t fIntrState = 0;
4889 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4890 {
4891 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4892 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4893
4894 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4895 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4896 {
4897 if (pCtx->eflags.Bits.u1IF)
4898 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4899 else
4900 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4901 }
4902 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4903 {
4904 /*
4905 * We can clear the inhibit force flag as even if we go back to the recompiler
4906 * without executing guest code in VT-x, the flag's condition to be cleared is
4907 * met and thus the cleared state is correct.
4908 */
4909 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4910 }
4911 }
4912
4913 /*
4914 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4915 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4916 * setting this would block host-NMIs and IRET will not clear the blocking.
4917 *
4918 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4919 *
4920 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4921 */
4922 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4923 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4924 && CPUMIsGuestNmiBlocking(pVCpu))
4925 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4926
4927 return fIntrState;
4928}
4929
4930
4931/**
4932 * Exports the exception intercepts required for guest execution in the VMCS.
4933 *
4934 * @returns VBox status code.
4935 * @param pVCpu The cross context virtual CPU structure.
4936 * @param pVmxTransient The VMX-transient structure.
4937 *
4938 * @remarks No-long-jump zone!!!
4939 */
4940static int hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
4941{
4942 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4943 {
4944 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4945 if ( !pVmxTransient->fIsNestedGuest
4946 && pVCpu->hm.s.fGIMTrapXcptUD)
4947 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4948 else
4949 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4950
4951 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4952 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4953 }
4954 return VINF_SUCCESS;
4955}
4956
4957
4958/**
4959 * Exports the guest's RIP into the guest-state area in the VMCS.
4960 *
4961 * @returns VBox status code.
4962 * @param pVCpu The cross context virtual CPU structure.
4963 *
4964 * @remarks No-long-jump zone!!!
4965 */
4966static int hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
4967{
4968 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
4969 {
4970 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
4971
4972 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
4973 AssertRC(rc);
4974
4975 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
4976 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
4977 }
4978 return VINF_SUCCESS;
4979}
4980
4981
4982/**
4983 * Exports the guest's RSP into the guest-state area in the VMCS.
4984 *
4985 * @returns VBox status code.
4986 * @param pVCpu The cross context virtual CPU structure.
4987 *
4988 * @remarks No-long-jump zone!!!
4989 */
4990static int hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
4991{
4992 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
4993 {
4994 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
4995
4996 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
4997 AssertRC(rc);
4998
4999 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5000 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5001 }
5002 return VINF_SUCCESS;
5003}
5004
5005
5006/**
5007 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5008 *
5009 * @returns VBox status code.
5010 * @param pVCpu The cross context virtual CPU structure.
5011 * @param pVmxTransient The VMX-transient structure.
5012 *
5013 * @remarks No-long-jump zone!!!
5014 */
5015static int hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5016{
5017 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5018 {
5019 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5020
5021 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5022 Let us assert it as such and use 32-bit VMWRITE. */
5023 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5024 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5025 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5026 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5027
5028 /*
5029 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5030 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5031 * can run the real-mode guest code under Virtual 8086 mode.
5032 */
5033 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5034 if (pVmcsInfo->RealMode.fRealOnV86Active)
5035 {
5036 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5037 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5038 Assert(!pVmxTransient->fIsNestedGuest);
5039 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5040 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5041 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5042 }
5043
5044 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5045 AssertRC(rc);
5046
5047 /*
5048 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5049 *
5050 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5051 * through the hypervisor debugger using EFLAGS.TF.
5052 */
5053 if ( !pVmxTransient->fIsNestedGuest
5054 && !pVCpu->hm.s.fSingleInstruction
5055 && fEFlags.Bits.u1TF)
5056 {
5057 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5058 * premature trips to ring-3 esp since IEM does not yet handle it. */
5059 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5060 AssertRC(rc);
5061 }
5062 /* else: for nested-guest currently handling while merging controls. */
5063
5064 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5065 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5066 }
5067 return VINF_SUCCESS;
5068}
5069
5070
5071#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5072/**
5073 * Copies the nested-guest VMCS to the shadow VMCS.
5074 *
5075 * @returns VBox status code.
5076 * @param pVCpu The cross context virtual CPU structure.
5077 * @param pVmcsInfo The VMCS info. object.
5078 *
5079 * @remarks No-long-jump zone!!!
5080 */
5081static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5082{
5083 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5084 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5085
5086 /*
5087 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5088 * current VMCS, as we may try saving guest lazy MSRs.
5089 *
5090 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5091 * calling the import VMCS code which is currently performing the guest MSR reads
5092 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5093 * and the rest of the VMX leave session machinery.
5094 */
5095 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5096
5097 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5098 if (RT_SUCCESS(rc))
5099 {
5100 /*
5101 * Copy all guest read/write VMCS fields.
5102 *
5103 * We don't check for VMWRITE failures here for performance reasons and
5104 * because they are not expected to fail, barring irrecoverable conditions
5105 * like hardware errors.
5106 */
5107 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5108 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5109 {
5110 uint64_t u64Val;
5111 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5112 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5113 VMXWriteVmcs64(uVmcsField, u64Val);
5114 }
5115
5116 /*
5117 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5118 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5119 */
5120 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5121 {
5122 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5123 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5124 {
5125 uint64_t u64Val;
5126 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5127 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5128 VMXWriteVmcs64(uVmcsField, u64Val);
5129 }
5130 }
5131
5132 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5133 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5134 }
5135
5136 ASMSetFlags(fEFlags);
5137 return rc;
5138}
5139
5140
5141/**
5142 * Copies the shadow VMCS to the nested-guest VMCS.
5143 *
5144 * @returns VBox status code.
5145 * @param pVCpu The cross context virtual CPU structure.
5146 * @param pVmcsInfo The VMCS info. object.
5147 *
5148 * @remarks Called with interrupts disabled.
5149 */
5150static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5151{
5152 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5153 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5154 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5155
5156 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5157 if (RT_SUCCESS(rc))
5158 {
5159 /*
5160 * Copy guest read/write fields from the shadow VMCS.
5161 * Guest read-only fields cannot be modified, so no need to copy them.
5162 *
5163 * We don't check for VMREAD failures here for performance reasons and
5164 * because they are not expected to fail, barring irrecoverable conditions
5165 * like hardware errors.
5166 */
5167 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5168 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5169 {
5170 uint64_t u64Val;
5171 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5172 VMXReadVmcs64(uVmcsField, &u64Val);
5173 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5174 }
5175
5176 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5177 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5178 }
5179 return rc;
5180}
5181
5182
5183/**
5184 * Enables VMCS shadowing for the given VMCS info. object.
5185 *
5186 * @param pVmcsInfo The VMCS info. object.
5187 *
5188 * @remarks No-long-jump zone!!!
5189 */
5190static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5191{
5192 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5193 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5194 {
5195 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5196 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5197 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5198 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5199 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5200 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5201 Log4Func(("Enabled\n"));
5202 }
5203}
5204
5205
5206/**
5207 * Disables VMCS shadowing for the given VMCS info. object.
5208 *
5209 * @param pVmcsInfo The VMCS info. object.
5210 *
5211 * @remarks No-long-jump zone!!!
5212 */
5213static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5214{
5215 /*
5216 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5217 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5218 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5219 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5220 *
5221 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5222 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5223 */
5224 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5225 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5226 {
5227 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5228 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5229 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5230 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5231 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5232 Log4Func(("Disabled\n"));
5233 }
5234}
5235#endif
5236
5237
5238/**
5239 * Exports the guest hardware-virtualization state.
5240 *
5241 * @returns VBox status code.
5242 * @param pVCpu The cross context virtual CPU structure.
5243 * @param pVmxTransient The VMX-transient structure.
5244 *
5245 * @remarks No-long-jump zone!!!
5246 */
5247static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5248{
5249 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5250 {
5251#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5252 /*
5253 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5254 * VMCS shadowing.
5255 */
5256 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5257 {
5258 /*
5259 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5260 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5261 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5262 *
5263 * We check for VMX root mode here in case the guest executes VMXOFF without
5264 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5265 * not clear the current VMCS pointer.
5266 */
5267 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5268 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5269 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5270 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5271 {
5272 /* Paranoia. */
5273 Assert(!pVmxTransient->fIsNestedGuest);
5274
5275 /*
5276 * For performance reasons, also check if the guest hypervisor's current VMCS
5277 * was newly loaded or modified before copying it to the shadow VMCS.
5278 */
5279 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5280 {
5281 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5282 AssertRCReturn(rc, rc);
5283 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5284 }
5285 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5286 }
5287 else
5288 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5289 }
5290#else
5291 NOREF(pVmxTransient);
5292#endif
5293 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5294 }
5295 return VINF_SUCCESS;
5296}
5297
5298
5299/**
5300 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5301 *
5302 * The guest FPU state is always pre-loaded hence we don't need to bother about
5303 * sharing FPU related CR0 bits between the guest and host.
5304 *
5305 * @returns VBox status code.
5306 * @param pVCpu The cross context virtual CPU structure.
5307 * @param pVmxTransient The VMX-transient structure.
5308 *
5309 * @remarks No-long-jump zone!!!
5310 */
5311static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5312{
5313 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5314 {
5315 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5316 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5317
5318 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5319 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5320 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5321 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5322 else
5323 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5324
5325 if (!pVmxTransient->fIsNestedGuest)
5326 {
5327 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5328 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5329 uint64_t const u64ShadowCr0 = u64GuestCr0;
5330 Assert(!RT_HI_U32(u64GuestCr0));
5331
5332 /*
5333 * Setup VT-x's view of the guest CR0.
5334 */
5335 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5336 if (pVM->hm.s.fNestedPaging)
5337 {
5338 if (CPUMIsGuestPagingEnabled(pVCpu))
5339 {
5340 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5341 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5342 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5343 }
5344 else
5345 {
5346 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5347 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5348 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5349 }
5350
5351 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5352 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5353 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5354 }
5355 else
5356 {
5357 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5358 u64GuestCr0 |= X86_CR0_WP;
5359 }
5360
5361 /*
5362 * Guest FPU bits.
5363 *
5364 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5365 * using CR0.TS.
5366 *
5367 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5368 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5369 */
5370 u64GuestCr0 |= X86_CR0_NE;
5371
5372 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5373 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5374
5375 /*
5376 * Update exception intercepts.
5377 */
5378 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5379 if (pVmcsInfo->RealMode.fRealOnV86Active)
5380 {
5381 Assert(PDMVmmDevHeapIsEnabled(pVM));
5382 Assert(pVM->hm.s.vmx.pRealModeTSS);
5383 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5384 }
5385 else
5386 {
5387 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5388 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5389 if (fInterceptMF)
5390 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5391 }
5392
5393 /* Additional intercepts for debugging, define these yourself explicitly. */
5394#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5395 uXcptBitmap |= 0
5396 | RT_BIT(X86_XCPT_BP)
5397 | RT_BIT(X86_XCPT_DE)
5398 | RT_BIT(X86_XCPT_NM)
5399 | RT_BIT(X86_XCPT_TS)
5400 | RT_BIT(X86_XCPT_UD)
5401 | RT_BIT(X86_XCPT_NP)
5402 | RT_BIT(X86_XCPT_SS)
5403 | RT_BIT(X86_XCPT_GP)
5404 | RT_BIT(X86_XCPT_PF)
5405 | RT_BIT(X86_XCPT_MF)
5406 ;
5407#elif defined(HMVMX_ALWAYS_TRAP_PF)
5408 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5409#endif
5410 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5411 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5412 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5413
5414 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5415 u64GuestCr0 |= fSetCr0;
5416 u64GuestCr0 &= fZapCr0;
5417 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5418
5419 /* Commit the CR0 and related fields to the guest VMCS. */
5420 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5421 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5422 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5423 {
5424 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5425 AssertRC(rc);
5426 }
5427 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5428 {
5429 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5430 AssertRC(rc);
5431 }
5432
5433 /* Update our caches. */
5434 pVmcsInfo->u32ProcCtls = uProcCtls;
5435 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5436
5437 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5438 }
5439 else
5440 {
5441 /*
5442 * With nested-guests, we may have extended the guest/host mask here since we
5443 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5444 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5445 * originally supplied. We must copy those bits from the nested-guest CR0 into
5446 * the nested-guest CR0 read-shadow.
5447 */
5448 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5449 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5450 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5451 Assert(!RT_HI_U32(u64GuestCr0));
5452 Assert(u64GuestCr0 & X86_CR0_NE);
5453
5454 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5455 u64GuestCr0 |= fSetCr0;
5456 u64GuestCr0 &= fZapCr0;
5457 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5458
5459 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5460 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5461 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5462
5463 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5464 }
5465
5466 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5467 }
5468
5469 return VINF_SUCCESS;
5470}
5471
5472
5473/**
5474 * Exports the guest control registers (CR3, CR4) into the guest-state area
5475 * in the VMCS.
5476 *
5477 * @returns VBox strict status code.
5478 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5479 * without unrestricted guest access and the VMMDev is not presently
5480 * mapped (e.g. EFI32).
5481 *
5482 * @param pVCpu The cross context virtual CPU structure.
5483 * @param pVmxTransient The VMX-transient structure.
5484 *
5485 * @remarks No-long-jump zone!!!
5486 */
5487static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5488{
5489 int rc = VINF_SUCCESS;
5490 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5491
5492 /*
5493 * Guest CR2.
5494 * It's always loaded in the assembler code. Nothing to do here.
5495 */
5496
5497 /*
5498 * Guest CR3.
5499 */
5500 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5501 {
5502 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5503
5504 if (pVM->hm.s.fNestedPaging)
5505 {
5506 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5507 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5508
5509 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5510 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5511 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5512 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5513
5514 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5515 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5516 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5517
5518 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5519 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5520 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5521 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5522 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5523 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5524 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5525
5526 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5527 AssertRC(rc);
5528
5529 uint64_t u64GuestCr3;
5530 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5531 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5532 || CPUMIsGuestPagingEnabledEx(pCtx))
5533 {
5534 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5535 if (CPUMIsGuestInPAEModeEx(pCtx))
5536 {
5537 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5538 AssertRC(rc);
5539 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5540 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5541 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5542 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5543 }
5544
5545 /*
5546 * The guest's view of its CR3 is unblemished with nested paging when the
5547 * guest is using paging or we have unrestricted guest execution to handle
5548 * the guest when it's not using paging.
5549 */
5550 u64GuestCr3 = pCtx->cr3;
5551 }
5552 else
5553 {
5554 /*
5555 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5556 * thinks it accesses physical memory directly, we use our identity-mapped
5557 * page table to map guest-linear to guest-physical addresses. EPT takes care
5558 * of translating it to host-physical addresses.
5559 */
5560 RTGCPHYS GCPhys;
5561 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5562
5563 /* We obtain it here every time as the guest could have relocated this PCI region. */
5564 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5565 if (RT_SUCCESS(rc))
5566 { /* likely */ }
5567 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5568 {
5569 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5570 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5571 }
5572 else
5573 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5574
5575 u64GuestCr3 = GCPhys;
5576 }
5577
5578 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5579 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5580 AssertRC(rc);
5581 }
5582 else
5583 {
5584 Assert(!pVmxTransient->fIsNestedGuest);
5585 /* Non-nested paging case, just use the hypervisor's CR3. */
5586 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5587
5588 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5589 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5590 AssertRC(rc);
5591 }
5592
5593 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5594 }
5595
5596 /*
5597 * Guest CR4.
5598 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5599 */
5600 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5601 {
5602 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5603 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5604
5605 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5606 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5607
5608 /*
5609 * With nested-guests, we may have extended the guest/host mask here (since we
5610 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5611 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5612 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5613 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5614 */
5615 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5616 uint64_t u64GuestCr4 = pCtx->cr4;
5617 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5618 ? pCtx->cr4
5619 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5620 Assert(!RT_HI_U32(u64GuestCr4));
5621
5622 /*
5623 * Setup VT-x's view of the guest CR4.
5624 *
5625 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5626 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5627 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5628 *
5629 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5630 */
5631 if (pVmcsInfo->RealMode.fRealOnV86Active)
5632 {
5633 Assert(pVM->hm.s.vmx.pRealModeTSS);
5634 Assert(PDMVmmDevHeapIsEnabled(pVM));
5635 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5636 }
5637
5638 if (pVM->hm.s.fNestedPaging)
5639 {
5640 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5641 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5642 {
5643 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5644 u64GuestCr4 |= X86_CR4_PSE;
5645 /* Our identity mapping is a 32-bit page directory. */
5646 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5647 }
5648 /* else use guest CR4.*/
5649 }
5650 else
5651 {
5652 Assert(!pVmxTransient->fIsNestedGuest);
5653
5654 /*
5655 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5656 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5657 */
5658 switch (pVCpu->hm.s.enmShadowMode)
5659 {
5660 case PGMMODE_REAL: /* Real-mode. */
5661 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5662 case PGMMODE_32_BIT: /* 32-bit paging. */
5663 {
5664 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5665 break;
5666 }
5667
5668 case PGMMODE_PAE: /* PAE paging. */
5669 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5670 {
5671 u64GuestCr4 |= X86_CR4_PAE;
5672 break;
5673 }
5674
5675 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5676 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5677 {
5678#ifdef VBOX_WITH_64_BITS_GUESTS
5679 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5680 Assert(u64GuestCr4 & X86_CR4_PAE);
5681 break;
5682#endif
5683 }
5684 default:
5685 AssertFailed();
5686 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5687 }
5688 }
5689
5690 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5691 u64GuestCr4 |= fSetCr4;
5692 u64GuestCr4 &= fZapCr4;
5693
5694 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5695 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5696 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5697
5698 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5699 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5700
5701 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5702
5703 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5704 }
5705 return rc;
5706}
5707
5708
5709/**
5710 * Exports the guest debug registers into the guest-state area in the VMCS.
5711 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5712 *
5713 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5714 *
5715 * @returns VBox status code.
5716 * @param pVCpu The cross context virtual CPU structure.
5717 * @param pVmxTransient The VMX-transient structure.
5718 *
5719 * @remarks No-long-jump zone!!!
5720 */
5721static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5722{
5723 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5724
5725 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5726 * stepping. */
5727 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5728 if (pVmxTransient->fIsNestedGuest)
5729 {
5730 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5731 AssertRC(rc);
5732
5733 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5734 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5735 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5736 AssertRC(rc);
5737 return VINF_SUCCESS;
5738 }
5739
5740#ifdef VBOX_STRICT
5741 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5742 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5743 {
5744 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5745 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5746 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5747 }
5748#endif
5749
5750 bool fSteppingDB = false;
5751 bool fInterceptMovDRx = false;
5752 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5753 if (pVCpu->hm.s.fSingleInstruction)
5754 {
5755 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5756 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5757 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5758 {
5759 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5760 Assert(fSteppingDB == false);
5761 }
5762 else
5763 {
5764 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5765 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5766 pVCpu->hm.s.fClearTrapFlag = true;
5767 fSteppingDB = true;
5768 }
5769 }
5770
5771 uint64_t u64GuestDr7;
5772 if ( fSteppingDB
5773 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5774 {
5775 /*
5776 * Use the combined guest and host DRx values found in the hypervisor register set
5777 * because the hypervisor debugger has breakpoints active or someone is single stepping
5778 * on the host side without a monitor trap flag.
5779 *
5780 * Note! DBGF expects a clean DR6 state before executing guest code.
5781 */
5782 if (!CPUMIsHyperDebugStateActive(pVCpu))
5783 {
5784 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5785 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5786 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5787 }
5788
5789 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5790 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5791 pVCpu->hm.s.fUsingHyperDR7 = true;
5792 fInterceptMovDRx = true;
5793 }
5794 else
5795 {
5796 /*
5797 * If the guest has enabled debug registers, we need to load them prior to
5798 * executing guest code so they'll trigger at the right time.
5799 */
5800 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5801 {
5802 if (!CPUMIsGuestDebugStateActive(pVCpu))
5803 {
5804 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5805 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5806 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5807 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5808 }
5809 Assert(!fInterceptMovDRx);
5810 }
5811 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5812 {
5813 /*
5814 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5815 * must intercept #DB in order to maintain a correct DR6 guest value, and
5816 * because we need to intercept it to prevent nested #DBs from hanging the
5817 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5818 */
5819 fInterceptMovDRx = true;
5820 }
5821
5822 /* Update DR7 with the actual guest value. */
5823 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5824 pVCpu->hm.s.fUsingHyperDR7 = false;
5825 }
5826
5827 if (fInterceptMovDRx)
5828 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5829 else
5830 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5831
5832 /*
5833 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5834 * monitor-trap flag and update our cache.
5835 */
5836 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5837 {
5838 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5839 AssertRC(rc);
5840 pVmcsInfo->u32ProcCtls = uProcCtls;
5841 }
5842
5843 /*
5844 * Update guest DR7.
5845 */
5846 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5847 AssertRC(rc);
5848
5849 /*
5850 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5851 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5852 *
5853 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5854 */
5855 if (fSteppingDB)
5856 {
5857 Assert(pVCpu->hm.s.fSingleInstruction);
5858 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5859
5860 uint32_t fIntrState = 0;
5861 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5862 AssertRC(rc);
5863
5864 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5865 {
5866 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5867 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5868 AssertRC(rc);
5869 }
5870 }
5871
5872 return VINF_SUCCESS;
5873}
5874
5875
5876#ifdef VBOX_STRICT
5877/**
5878 * Strict function to validate segment registers.
5879 *
5880 * @param pVCpu The cross context virtual CPU structure.
5881 * @param pVmcsInfo The VMCS info. object.
5882 *
5883 * @remarks Will import guest CR0 on strict builds during validation of
5884 * segments.
5885 */
5886static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5887{
5888 /*
5889 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5890 *
5891 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5892 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5893 * unusable bit and doesn't change the guest-context value.
5894 */
5895 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5896 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5897 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5898 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5899 && ( !CPUMIsGuestInRealModeEx(pCtx)
5900 && !CPUMIsGuestInV86ModeEx(pCtx)))
5901 {
5902 /* Protected mode checks */
5903 /* CS */
5904 Assert(pCtx->cs.Attr.n.u1Present);
5905 Assert(!(pCtx->cs.Attr.u & 0xf00));
5906 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5907 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5908 || !(pCtx->cs.Attr.n.u1Granularity));
5909 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5910 || (pCtx->cs.Attr.n.u1Granularity));
5911 /* CS cannot be loaded with NULL in protected mode. */
5912 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5913 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5914 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5915 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5916 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5917 else
5918 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5919 /* SS */
5920 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5921 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5922 if ( !(pCtx->cr0 & X86_CR0_PE)
5923 || pCtx->cs.Attr.n.u4Type == 3)
5924 {
5925 Assert(!pCtx->ss.Attr.n.u2Dpl);
5926 }
5927 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5928 {
5929 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5930 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5931 Assert(pCtx->ss.Attr.n.u1Present);
5932 Assert(!(pCtx->ss.Attr.u & 0xf00));
5933 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5934 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5935 || !(pCtx->ss.Attr.n.u1Granularity));
5936 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5937 || (pCtx->ss.Attr.n.u1Granularity));
5938 }
5939 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5940 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5941 {
5942 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5943 Assert(pCtx->ds.Attr.n.u1Present);
5944 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5945 Assert(!(pCtx->ds.Attr.u & 0xf00));
5946 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5947 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5948 || !(pCtx->ds.Attr.n.u1Granularity));
5949 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5950 || (pCtx->ds.Attr.n.u1Granularity));
5951 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5952 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5953 }
5954 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5955 {
5956 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5957 Assert(pCtx->es.Attr.n.u1Present);
5958 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5959 Assert(!(pCtx->es.Attr.u & 0xf00));
5960 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5961 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5962 || !(pCtx->es.Attr.n.u1Granularity));
5963 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5964 || (pCtx->es.Attr.n.u1Granularity));
5965 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5966 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5967 }
5968 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5969 {
5970 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5971 Assert(pCtx->fs.Attr.n.u1Present);
5972 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5973 Assert(!(pCtx->fs.Attr.u & 0xf00));
5974 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5975 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5976 || !(pCtx->fs.Attr.n.u1Granularity));
5977 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
5978 || (pCtx->fs.Attr.n.u1Granularity));
5979 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5980 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5981 }
5982 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
5983 {
5984 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5985 Assert(pCtx->gs.Attr.n.u1Present);
5986 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
5987 Assert(!(pCtx->gs.Attr.u & 0xf00));
5988 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
5989 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
5990 || !(pCtx->gs.Attr.n.u1Granularity));
5991 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
5992 || (pCtx->gs.Attr.n.u1Granularity));
5993 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5994 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5995 }
5996 /* 64-bit capable CPUs. */
5997 Assert(!RT_HI_U32(pCtx->cs.u64Base));
5998 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
5999 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6000 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6001 }
6002 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6003 || ( CPUMIsGuestInRealModeEx(pCtx)
6004 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6005 {
6006 /* Real and v86 mode checks. */
6007 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6008 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6009 if (pVmcsInfo->RealMode.fRealOnV86Active)
6010 {
6011 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6012 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6013 }
6014 else
6015 {
6016 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6017 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6018 }
6019
6020 /* CS */
6021 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6022 Assert(pCtx->cs.u32Limit == 0xffff);
6023 Assert(u32CSAttr == 0xf3);
6024 /* SS */
6025 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6026 Assert(pCtx->ss.u32Limit == 0xffff);
6027 Assert(u32SSAttr == 0xf3);
6028 /* DS */
6029 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6030 Assert(pCtx->ds.u32Limit == 0xffff);
6031 Assert(u32DSAttr == 0xf3);
6032 /* ES */
6033 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6034 Assert(pCtx->es.u32Limit == 0xffff);
6035 Assert(u32ESAttr == 0xf3);
6036 /* FS */
6037 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6038 Assert(pCtx->fs.u32Limit == 0xffff);
6039 Assert(u32FSAttr == 0xf3);
6040 /* GS */
6041 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6042 Assert(pCtx->gs.u32Limit == 0xffff);
6043 Assert(u32GSAttr == 0xf3);
6044 /* 64-bit capable CPUs. */
6045 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6046 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6047 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6048 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6049 }
6050}
6051#endif /* VBOX_STRICT */
6052
6053
6054/**
6055 * Exports a guest segment register into the guest-state area in the VMCS.
6056 *
6057 * @returns VBox status code.
6058 * @param pVCpu The cross context virtual CPU structure.
6059 * @param pVmcsInfo The VMCS info. object.
6060 * @param iSegReg The segment register number (X86_SREG_XXX).
6061 * @param pSelReg Pointer to the segment selector.
6062 *
6063 * @remarks No-long-jump zone!!!
6064 */
6065static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6066{
6067 Assert(iSegReg < X86_SREG_COUNT);
6068 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6069 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6070 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6071 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6072
6073 uint32_t u32Access = pSelReg->Attr.u;
6074 if (pVmcsInfo->RealMode.fRealOnV86Active)
6075 {
6076 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6077 u32Access = 0xf3;
6078 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6079 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6080 RT_NOREF_PV(pVCpu);
6081 }
6082 else
6083 {
6084 /*
6085 * The way to differentiate between whether this is really a null selector or was just
6086 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6087 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6088 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6089 * NULL selectors loaded in protected-mode have their attribute as 0.
6090 */
6091 if (!u32Access)
6092 u32Access = X86DESCATTR_UNUSABLE;
6093 }
6094
6095 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6096 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6097 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6098
6099 /*
6100 * Commit it to the VMCS.
6101 */
6102 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6103 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6104 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6105 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6106 return VINF_SUCCESS;
6107}
6108
6109
6110/**
6111 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6112 * area in the VMCS.
6113 *
6114 * @returns VBox status code.
6115 * @param pVCpu The cross context virtual CPU structure.
6116 * @param pVmxTransient The VMX-transient structure.
6117 *
6118 * @remarks Will import guest CR0 on strict builds during validation of
6119 * segments.
6120 * @remarks No-long-jump zone!!!
6121 */
6122static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6123{
6124 int rc = VERR_INTERNAL_ERROR_5;
6125 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6126 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6127 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6128
6129 /*
6130 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6131 */
6132 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6133 {
6134#ifdef VBOX_WITH_REM
6135 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6136 {
6137 Assert(!pVmxTransient->fIsNestedGuest);
6138 Assert(pVM->hm.s.vmx.pRealModeTSS);
6139 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6140 if ( pVmcsInfo->fWasInRealMode
6141 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6142 {
6143 /*
6144 * Notify the recompiler must flush its code-cache as the guest -may-
6145 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6146 */
6147 REMFlushTBs(pVM);
6148 Log4Func(("Switch to protected mode detected!\n"));
6149 pVmcsInfo->fWasInRealMode = false;
6150 }
6151 }
6152#endif
6153 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6154 {
6155 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6156 if (pVmcsInfo->RealMode.fRealOnV86Active)
6157 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6158 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6159 AssertRC(rc);
6160 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6161 }
6162
6163 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6164 {
6165 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6166 if (pVmcsInfo->RealMode.fRealOnV86Active)
6167 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6168 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6169 AssertRC(rc);
6170 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6171 }
6172
6173 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6174 {
6175 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6176 if (pVmcsInfo->RealMode.fRealOnV86Active)
6177 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6178 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6179 AssertRC(rc);
6180 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6181 }
6182
6183 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6184 {
6185 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6186 if (pVmcsInfo->RealMode.fRealOnV86Active)
6187 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6188 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6189 AssertRC(rc);
6190 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6191 }
6192
6193 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6194 {
6195 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6196 if (pVmcsInfo->RealMode.fRealOnV86Active)
6197 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6198 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6199 AssertRC(rc);
6200 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6201 }
6202
6203 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6204 {
6205 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6206 if (pVmcsInfo->RealMode.fRealOnV86Active)
6207 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6208 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6209 AssertRC(rc);
6210 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6211 }
6212
6213#ifdef VBOX_STRICT
6214 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6215#endif
6216 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6217 pCtx->cs.Attr.u));
6218 }
6219
6220 /*
6221 * Guest TR.
6222 */
6223 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6224 {
6225 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6226
6227 /*
6228 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6229 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6230 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6231 */
6232 uint16_t u16Sel;
6233 uint32_t u32Limit;
6234 uint64_t u64Base;
6235 uint32_t u32AccessRights;
6236 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6237 {
6238 u16Sel = pCtx->tr.Sel;
6239 u32Limit = pCtx->tr.u32Limit;
6240 u64Base = pCtx->tr.u64Base;
6241 u32AccessRights = pCtx->tr.Attr.u;
6242 }
6243 else
6244 {
6245 Assert(!pVmxTransient->fIsNestedGuest);
6246 Assert(pVM->hm.s.vmx.pRealModeTSS);
6247 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6248
6249 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6250 RTGCPHYS GCPhys;
6251 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6252 AssertRCReturn(rc, rc);
6253
6254 X86DESCATTR DescAttr;
6255 DescAttr.u = 0;
6256 DescAttr.n.u1Present = 1;
6257 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6258
6259 u16Sel = 0;
6260 u32Limit = HM_VTX_TSS_SIZE;
6261 u64Base = GCPhys;
6262 u32AccessRights = DescAttr.u;
6263 }
6264
6265 /* Validate. */
6266 Assert(!(u16Sel & RT_BIT(2)));
6267 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6268 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6269 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6270 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6271 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6272 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6273 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6274 Assert( (u32Limit & 0xfff) == 0xfff
6275 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6276 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6277 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6278
6279 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6280 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6281 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6282 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6283
6284 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6285 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6286 }
6287
6288 /*
6289 * Guest GDTR.
6290 */
6291 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6292 {
6293 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6294
6295 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6296 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6297
6298 /* Validate. */
6299 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6300
6301 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6302 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6303 }
6304
6305 /*
6306 * Guest LDTR.
6307 */
6308 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6309 {
6310 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6311
6312 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6313 uint32_t u32Access;
6314 if ( !pVmxTransient->fIsNestedGuest
6315 && !pCtx->ldtr.Attr.u)
6316 u32Access = X86DESCATTR_UNUSABLE;
6317 else
6318 u32Access = pCtx->ldtr.Attr.u;
6319
6320 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6321 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6322 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6323 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6324
6325 /* Validate. */
6326 if (!(u32Access & X86DESCATTR_UNUSABLE))
6327 {
6328 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6329 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6330 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6331 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6332 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6333 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6334 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6335 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6336 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6337 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6338 }
6339
6340 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6341 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6342 }
6343
6344 /*
6345 * Guest IDTR.
6346 */
6347 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6348 {
6349 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6350
6351 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6352 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6353
6354 /* Validate. */
6355 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6356
6357 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6358 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6359 }
6360
6361 return VINF_SUCCESS;
6362}
6363
6364
6365/**
6366 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6367 * areas.
6368 *
6369 * These MSRs will automatically be loaded to the host CPU on every successful
6370 * VM-entry and stored from the host CPU on every successful VM-exit.
6371 *
6372 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6373 * actual host MSR values are not- updated here for performance reasons. See
6374 * hmR0VmxExportHostMsrs().
6375 *
6376 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6377 *
6378 * @returns VBox status code.
6379 * @param pVCpu The cross context virtual CPU structure.
6380 * @param pVmxTransient The VMX-transient structure.
6381 *
6382 * @remarks No-long-jump zone!!!
6383 */
6384static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6385{
6386 AssertPtr(pVCpu);
6387 AssertPtr(pVmxTransient);
6388
6389 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6390 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6391
6392 /*
6393 * MSRs that we use the auto-load/store MSR area in the VMCS.
6394 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6395 * nothing to do here. The host MSR values are updated when it's safe in
6396 * hmR0VmxLazySaveHostMsrs().
6397 *
6398 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6399 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6400 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6401 * for any MSR that are not part of the lazy MSRs so we do not need to place
6402 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6403 */
6404 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6405 {
6406 /* No auto-load/store MSRs currently. */
6407 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6408 }
6409
6410 /*
6411 * Guest Sysenter MSRs.
6412 */
6413 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6414 {
6415 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6416
6417 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6418 {
6419 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6420 AssertRC(rc);
6421 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6422 }
6423
6424 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6425 {
6426 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6427 AssertRC(rc);
6428 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6429 }
6430
6431 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6432 {
6433 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6434 AssertRC(rc);
6435 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6436 }
6437 }
6438
6439 /*
6440 * Guest/host EFER MSR.
6441 */
6442 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6443 {
6444 /* Whether we are using the VMCS to swap the EFER MSR must have been
6445 determined earlier while exporting VM-entry/VM-exit controls. */
6446 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6447 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6448
6449 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6450 {
6451 /*
6452 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6453 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6454 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6455 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6456 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6457 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6458 * during VM-entry.
6459 */
6460 uint64_t uGuestEferMsr = pCtx->msrEFER;
6461 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6462 {
6463 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6464 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6465 else
6466 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6467 }
6468
6469 /*
6470 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6471 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6472 */
6473 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6474 {
6475 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6476 AssertRC(rc);
6477 }
6478 else
6479 {
6480 /*
6481 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6482 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6483 */
6484 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6485 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6486 AssertRCReturn(rc, rc);
6487 }
6488
6489 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6490 }
6491 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6492 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6493
6494 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6495 }
6496
6497 /*
6498 * Other MSRs.
6499 * Speculation Control (R/W).
6500 */
6501 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6502 {
6503 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6504 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6505 {
6506 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6507 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6508 AssertRCReturn(rc, rc);
6509 }
6510 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6511 }
6512
6513 return VINF_SUCCESS;
6514}
6515
6516
6517/**
6518 * Selects up the appropriate function to run guest code.
6519 *
6520 * @returns VBox status code.
6521 * @param pVCpu The cross context virtual CPU structure.
6522 * @param pVmxTransient The VMX-transient structure.
6523 *
6524 * @remarks No-long-jump zone!!!
6525 */
6526static int hmR0VmxSelectVMRunHandler(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6527{
6528 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6529 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6530
6531 if (CPUMIsGuestInLongModeEx(pCtx))
6532 {
6533#ifndef VBOX_WITH_64_BITS_GUESTS
6534 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6535#else
6536 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6537 /* Guest is in long mode, use the 64-bit handler (host is 64-bit). */
6538 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6539#endif
6540 }
6541 else
6542 {
6543 /* Guest is not in long mode, use the 32-bit handler. */
6544 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6545 }
6546 Assert(pVmcsInfo->pfnStartVM);
6547 return VINF_SUCCESS;
6548}
6549
6550
6551/**
6552 * Wrapper for running the guest code in VT-x.
6553 *
6554 * @returns VBox status code, no informational status codes.
6555 * @param pVCpu The cross context virtual CPU structure.
6556 * @param pVmxTransient The VMX-transient structure.
6557 *
6558 * @remarks No-long-jump zone!!!
6559 */
6560DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6561{
6562 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6563 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6564 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6565
6566 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6567
6568 /*
6569 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6570 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6571 * callee-saved and thus the need for this XMM wrapper.
6572 *
6573 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6574 */
6575 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6576 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6577 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6578#ifdef VBOX_WITH_KERNEL_USING_XMM
6579 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6580#else
6581 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6582#endif
6583 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6584 return rc;
6585}
6586
6587
6588/**
6589 * Reports world-switch error and dumps some useful debug info.
6590 *
6591 * @param pVCpu The cross context virtual CPU structure.
6592 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6593 * @param pVmxTransient The VMX-transient structure (only
6594 * exitReason updated).
6595 */
6596static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6597{
6598 Assert(pVCpu);
6599 Assert(pVmxTransient);
6600 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6601
6602 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6603 switch (rcVMRun)
6604 {
6605 case VERR_VMX_INVALID_VMXON_PTR:
6606 AssertFailed();
6607 break;
6608 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6609 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6610 {
6611 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6612 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6613 AssertRC(rc);
6614 hmR0VmxReadExitQualVmcs(pVmxTransient);
6615
6616 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6617 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6618 Cannot do it here as we may have been long preempted. */
6619
6620#ifdef VBOX_STRICT
6621 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6622 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6623 pVmxTransient->uExitReason));
6624 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6625 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6626 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6627 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6628 else
6629 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6630 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6631 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6632
6633 static struct
6634 {
6635 /** Name of the field to log. */
6636 const char *pszName;
6637 /** The VMCS field. */
6638 uint32_t uVmcsField;
6639 /** Whether host support of this field needs to be checked. */
6640 bool fCheckSupport;
6641 } const s_aVmcsFields[] =
6642 {
6643 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6644 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6645 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6646 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6647 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6648 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6649 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6650 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6651 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6652 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6653 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6654 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6655 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6656 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6657 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6658 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6659 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6660 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6661 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6662 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6663 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6664 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6665 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6666 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6667 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6668 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6669 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6670 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6671 /* The order of selector fields below are fixed! */
6672 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6673 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6674 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6675 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6676 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6677 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6678 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6679 /* End of ordered selector fields. */
6680 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6681 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6682 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6683 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6684 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6685 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6686 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6687 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6688 };
6689
6690 RTGDTR HostGdtr;
6691 ASMGetGDTR(&HostGdtr);
6692
6693 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6694 for (uint32_t i = 0; i < cVmcsFields; i++)
6695 {
6696 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6697
6698 bool fSupported;
6699 if (!s_aVmcsFields[i].fCheckSupport)
6700 fSupported = true;
6701 else
6702 {
6703 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6704 switch (uVmcsField)
6705 {
6706 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6707 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6708 case VMX_VMCS32_CTRL_PROC_EXEC2:
6709 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6710 break;
6711 default:
6712 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6713 }
6714 }
6715
6716 if (fSupported)
6717 {
6718 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6719 switch (uWidth)
6720 {
6721 case VMX_VMCSFIELD_WIDTH_16BIT:
6722 {
6723 uint16_t u16Val;
6724 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6725 AssertRC(rc);
6726 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6727
6728 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6729 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6730 {
6731 if (u16Val < HostGdtr.cbGdt)
6732 {
6733 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6734 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6735 "Host FS", "Host GS", "Host TR" };
6736 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6737 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6738 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6739 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6740 }
6741 else
6742 Log4((" Selector value exceeds GDT limit!\n"));
6743 }
6744 break;
6745 }
6746
6747 case VMX_VMCSFIELD_WIDTH_32BIT:
6748 {
6749 uint32_t u32Val;
6750 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6751 AssertRC(rc);
6752 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6753 break;
6754 }
6755
6756 case VMX_VMCSFIELD_WIDTH_64BIT:
6757 case VMX_VMCSFIELD_WIDTH_NATURAL:
6758 {
6759 uint64_t u64Val;
6760 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6761 AssertRC(rc);
6762 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6763 break;
6764 }
6765 }
6766 }
6767 }
6768
6769 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6770 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6771 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6772 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6773 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6774 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6775#endif /* VBOX_STRICT */
6776 break;
6777 }
6778
6779 default:
6780 /* Impossible */
6781 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6782 break;
6783 }
6784}
6785
6786
6787/**
6788 * Sets up the usage of TSC-offsetting and updates the VMCS.
6789 *
6790 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6791 * VMX-preemption timer.
6792 *
6793 * @returns VBox status code.
6794 * @param pVCpu The cross context virtual CPU structure.
6795 * @param pVmxTransient The VMX-transient structure.
6796 *
6797 * @remarks No-long-jump zone!!!
6798 */
6799static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6800{
6801 bool fOffsettedTsc;
6802 bool fParavirtTsc;
6803 uint64_t uTscOffset;
6804 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6805 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6806
6807 if (pVM->hm.s.vmx.fUsePreemptTimer)
6808 {
6809 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6810
6811 /* Make sure the returned values have sane upper and lower boundaries. */
6812 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6813 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6814 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6815 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6816
6817 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6818 * preemption timers here. We probably need to clamp the preemption timer,
6819 * after converting the timer value to the host. */
6820 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6821 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6822 AssertRC(rc);
6823 }
6824 else
6825 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6826
6827 if (fParavirtTsc)
6828 {
6829 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6830 information before every VM-entry, hence disable it for performance sake. */
6831#if 0
6832 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6833 AssertRC(rc);
6834#endif
6835 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6836 }
6837
6838 if ( fOffsettedTsc
6839 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6840 {
6841 if (pVmxTransient->fIsNestedGuest)
6842 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6843 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6844 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6845 }
6846 else
6847 {
6848 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6849 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6850 }
6851}
6852
6853
6854/**
6855 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6856 * VM-exit interruption info type.
6857 *
6858 * @returns The IEM exception flags.
6859 * @param uVector The event vector.
6860 * @param uVmxEventType The VMX event type.
6861 *
6862 * @remarks This function currently only constructs flags required for
6863 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6864 * and CR2 aspects of an exception are not included).
6865 */
6866static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6867{
6868 uint32_t fIemXcptFlags;
6869 switch (uVmxEventType)
6870 {
6871 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6872 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6873 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6874 break;
6875
6876 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6877 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6878 break;
6879
6880 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6881 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6882 break;
6883
6884 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6885 {
6886 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6887 if (uVector == X86_XCPT_BP)
6888 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6889 else if (uVector == X86_XCPT_OF)
6890 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6891 else
6892 {
6893 fIemXcptFlags = 0;
6894 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6895 }
6896 break;
6897 }
6898
6899 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6900 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6901 break;
6902
6903 default:
6904 fIemXcptFlags = 0;
6905 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6906 break;
6907 }
6908 return fIemXcptFlags;
6909}
6910
6911
6912/**
6913 * Sets an event as a pending event to be injected into the guest.
6914 *
6915 * @param pVCpu The cross context virtual CPU structure.
6916 * @param u32IntInfo The VM-entry interruption-information field.
6917 * @param cbInstr The VM-entry instruction length in bytes (for
6918 * software interrupts, exceptions and privileged
6919 * software exceptions).
6920 * @param u32ErrCode The VM-entry exception error code.
6921 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6922 * page-fault.
6923 */
6924DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6925 RTGCUINTPTR GCPtrFaultAddress)
6926{
6927 Assert(!pVCpu->hm.s.Event.fPending);
6928 pVCpu->hm.s.Event.fPending = true;
6929 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6930 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6931 pVCpu->hm.s.Event.cbInstr = cbInstr;
6932 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6933}
6934
6935
6936/**
6937 * Sets an external interrupt as pending-for-injection into the VM.
6938 *
6939 * @param pVCpu The cross context virtual CPU structure.
6940 * @param u8Interrupt The external interrupt vector.
6941 */
6942DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6943{
6944 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6945 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6946 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6947 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6948 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6949}
6950
6951
6952/**
6953 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6954 *
6955 * @param pVCpu The cross context virtual CPU structure.
6956 */
6957DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6958{
6959 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6960 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6961 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6962 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6963 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6964}
6965
6966
6967/**
6968 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6969 *
6970 * @param pVCpu The cross context virtual CPU structure.
6971 */
6972DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6973{
6974 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6975 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6976 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6977 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6978 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6979}
6980
6981
6982/**
6983 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6984 *
6985 * @param pVCpu The cross context virtual CPU structure.
6986 */
6987DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6988{
6989 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6990 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6991 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6992 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6993 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6994}
6995
6996
6997/**
6998 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6999 *
7000 * @param pVCpu The cross context virtual CPU structure.
7001 */
7002DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
7003{
7004 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7005 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7006 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7007 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7008 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7009}
7010
7011
7012#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7013/**
7014 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7015 *
7016 * @param pVCpu The cross context virtual CPU structure.
7017 * @param u32ErrCode The error code for the general-protection exception.
7018 */
7019DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7020{
7021 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7022 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7023 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7024 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7025 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7026}
7027
7028
7029/**
7030 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7031 *
7032 * @param pVCpu The cross context virtual CPU structure.
7033 * @param u32ErrCode The error code for the stack exception.
7034 */
7035DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7036{
7037 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7038 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7039 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7040 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7041 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7042}
7043#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7044
7045
7046/**
7047 * Fixes up attributes for the specified segment register.
7048 *
7049 * @param pVCpu The cross context virtual CPU structure.
7050 * @param pSelReg The segment register that needs fixing.
7051 * @param idxSel The VMCS field for the corresponding segment register.
7052 */
7053static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7054{
7055 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7056
7057 /*
7058 * If VT-x marks the segment as unusable, most other bits remain undefined:
7059 * - For CS the L, D and G bits have meaning.
7060 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7061 * - For the remaining data segments no bits are defined.
7062 *
7063 * The present bit and the unusable bit has been observed to be set at the
7064 * same time (the selector was supposed to be invalid as we started executing
7065 * a V8086 interrupt in ring-0).
7066 *
7067 * What should be important for the rest of the VBox code, is that the P bit is
7068 * cleared. Some of the other VBox code recognizes the unusable bit, but
7069 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7070 * safe side here, we'll strip off P and other bits we don't care about. If
7071 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7072 *
7073 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7074 */
7075#ifdef VBOX_STRICT
7076 uint32_t const uAttr = pSelReg->Attr.u;
7077#endif
7078
7079 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7080 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7081 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7082
7083#ifdef VBOX_STRICT
7084 VMMRZCallRing3Disable(pVCpu);
7085 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7086# ifdef DEBUG_bird
7087 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7088 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7089 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7090# endif
7091 VMMRZCallRing3Enable(pVCpu);
7092 NOREF(uAttr);
7093#endif
7094 RT_NOREF2(pVCpu, idxSel);
7095}
7096
7097
7098/**
7099 * Imports a guest segment register from the current VMCS into the guest-CPU
7100 * context.
7101 *
7102 * @param pVCpu The cross context virtual CPU structure.
7103 * @param iSegReg The segment register number (X86_SREG_XXX).
7104 *
7105 * @remarks Called with interrupts and/or preemption disabled.
7106 */
7107static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7108{
7109 Assert(iSegReg < X86_SREG_COUNT);
7110
7111 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7112 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7113 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7114 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7115
7116 uint16_t u16Sel;
7117 uint64_t u64Base;
7118 uint32_t u32Limit, u32Attr;
7119 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7120 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7121 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7122 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7123
7124 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7125 pSelReg->Sel = u16Sel;
7126 pSelReg->ValidSel = u16Sel;
7127 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7128 pSelReg->u32Limit = u32Limit;
7129 pSelReg->u64Base = u64Base;
7130 pSelReg->Attr.u = u32Attr;
7131 if (u32Attr & X86DESCATTR_UNUSABLE)
7132 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7133}
7134
7135
7136/**
7137 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7138 *
7139 * @param pVCpu The cross context virtual CPU structure.
7140 *
7141 * @remarks Called with interrupts and/or preemption disabled.
7142 */
7143static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7144{
7145 uint16_t u16Sel;
7146 uint64_t u64Base;
7147 uint32_t u32Limit, u32Attr;
7148 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7149 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7150 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7151 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7152
7153 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7154 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7155 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7156 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7157 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7158 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7159 if (u32Attr & X86DESCATTR_UNUSABLE)
7160 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7161}
7162
7163
7164/**
7165 * Imports the guest TR from the current VMCS into the guest-CPU context.
7166 *
7167 * @param pVCpu The cross context virtual CPU structure.
7168 *
7169 * @remarks Called with interrupts and/or preemption disabled.
7170 */
7171static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7172{
7173 uint16_t u16Sel;
7174 uint64_t u64Base;
7175 uint32_t u32Limit, u32Attr;
7176 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7177 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7178 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7179 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7180
7181 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7182 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7183 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7184 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7185 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7186 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7187 /* TR is the only selector that can never be unusable. */
7188 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7189}
7190
7191
7192/**
7193 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7194 *
7195 * @param pVCpu The cross context virtual CPU structure.
7196 *
7197 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7198 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7199 * instead!!!
7200 */
7201static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7202{
7203 uint64_t u64Val;
7204 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7205 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7206 {
7207 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7208 AssertRC(rc);
7209
7210 pCtx->rip = u64Val;
7211 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7212 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7213 }
7214}
7215
7216
7217/**
7218 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7219 *
7220 * @param pVCpu The cross context virtual CPU structure.
7221 * @param pVmcsInfo The VMCS info. object.
7222 *
7223 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7224 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7225 * instead!!!
7226 */
7227static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7228{
7229 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7230 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7231 {
7232 uint64_t u64Val;
7233 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7234 AssertRC(rc);
7235
7236 pCtx->rflags.u64 = u64Val;
7237 if (pVmcsInfo->RealMode.fRealOnV86Active)
7238 {
7239 pCtx->eflags.Bits.u1VM = 0;
7240 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7241 }
7242 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7243 }
7244}
7245
7246
7247/**
7248 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7249 * context.
7250 *
7251 * @param pVCpu The cross context virtual CPU structure.
7252 * @param pVmcsInfo The VMCS info. object.
7253 *
7254 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7255 * do not log!
7256 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7257 * instead!!!
7258 */
7259static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7260{
7261 uint32_t u32Val;
7262 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7263 if (!u32Val)
7264 {
7265 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7266 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7267 CPUMSetGuestNmiBlocking(pVCpu, false);
7268 }
7269 else
7270 {
7271 /*
7272 * We must import RIP here to set our EM interrupt-inhibited state.
7273 * We also import RFLAGS as our code that evaluates pending interrupts
7274 * before VM-entry requires it.
7275 */
7276 hmR0VmxImportGuestRip(pVCpu);
7277 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7278
7279 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7280 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7281 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7282 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7283
7284 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7285 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7286 }
7287}
7288
7289
7290/**
7291 * Worker for VMXR0ImportStateOnDemand.
7292 *
7293 * @returns VBox status code.
7294 * @param pVCpu The cross context virtual CPU structure.
7295 * @param pVmcsInfo The VMCS info. object.
7296 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7297 */
7298static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7299{
7300 int rc = VINF_SUCCESS;
7301 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7302 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7303 uint32_t u32Val;
7304
7305 /*
7306 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7307 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7308 * neither are other host platforms.
7309 *
7310 * Committing this temporarily as it prevents BSOD.
7311 *
7312 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7313 */
7314#ifdef RT_OS_WINDOWS
7315 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7316 return VERR_HM_IPE_1;
7317#endif
7318
7319 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7320
7321 /*
7322 * We disable interrupts to make the updating of the state and in particular
7323 * the fExtrn modification atomic wrt to preemption hooks.
7324 */
7325 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7326
7327 fWhat &= pCtx->fExtrn;
7328 if (fWhat)
7329 {
7330 do
7331 {
7332 if (fWhat & CPUMCTX_EXTRN_RIP)
7333 hmR0VmxImportGuestRip(pVCpu);
7334
7335 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7336 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7337
7338 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7339 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7340
7341 if (fWhat & CPUMCTX_EXTRN_RSP)
7342 {
7343 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7344 AssertRC(rc);
7345 }
7346
7347 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7348 {
7349 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7350 if (fWhat & CPUMCTX_EXTRN_CS)
7351 {
7352 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7353 hmR0VmxImportGuestRip(pVCpu);
7354 if (fRealOnV86Active)
7355 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7356 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7357 }
7358 if (fWhat & CPUMCTX_EXTRN_SS)
7359 {
7360 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7361 if (fRealOnV86Active)
7362 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7363 }
7364 if (fWhat & CPUMCTX_EXTRN_DS)
7365 {
7366 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7367 if (fRealOnV86Active)
7368 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7369 }
7370 if (fWhat & CPUMCTX_EXTRN_ES)
7371 {
7372 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7373 if (fRealOnV86Active)
7374 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7375 }
7376 if (fWhat & CPUMCTX_EXTRN_FS)
7377 {
7378 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7379 if (fRealOnV86Active)
7380 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7381 }
7382 if (fWhat & CPUMCTX_EXTRN_GS)
7383 {
7384 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7385 if (fRealOnV86Active)
7386 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7387 }
7388 }
7389
7390 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7391 {
7392 if (fWhat & CPUMCTX_EXTRN_LDTR)
7393 hmR0VmxImportGuestLdtr(pVCpu);
7394
7395 if (fWhat & CPUMCTX_EXTRN_GDTR)
7396 {
7397 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7398 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7399 pCtx->gdtr.cbGdt = u32Val;
7400 }
7401
7402 /* Guest IDTR. */
7403 if (fWhat & CPUMCTX_EXTRN_IDTR)
7404 {
7405 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7406 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7407 pCtx->idtr.cbIdt = u32Val;
7408 }
7409
7410 /* Guest TR. */
7411 if (fWhat & CPUMCTX_EXTRN_TR)
7412 {
7413 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7414 don't need to import that one. */
7415 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7416 hmR0VmxImportGuestTr(pVCpu);
7417 }
7418 }
7419
7420 if (fWhat & CPUMCTX_EXTRN_DR7)
7421 {
7422 if (!pVCpu->hm.s.fUsingHyperDR7)
7423 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7424 }
7425
7426 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7427 {
7428 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7429 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7430 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7431 pCtx->SysEnter.cs = u32Val;
7432 }
7433
7434 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7435 {
7436 if ( pVM->hm.s.fAllow64BitGuests
7437 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7438 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7439 }
7440
7441 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7442 {
7443 if ( pVM->hm.s.fAllow64BitGuests
7444 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7445 {
7446 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7447 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7448 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7449 }
7450 }
7451
7452 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7453 {
7454 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7455 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7456 Assert(pMsrs);
7457 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7458 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7459 for (uint32_t i = 0; i < cMsrs; i++)
7460 {
7461 uint32_t const idMsr = pMsrs[i].u32Msr;
7462 switch (idMsr)
7463 {
7464 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7465 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7466 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7467 default:
7468 {
7469 pCtx->fExtrn = 0;
7470 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7471 ASMSetFlags(fEFlags);
7472 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7473 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7474 }
7475 }
7476 }
7477 }
7478
7479 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7480 {
7481 if (fWhat & CPUMCTX_EXTRN_CR0)
7482 {
7483 uint64_t u64Cr0;
7484 uint64_t u64Shadow;
7485 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7486 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7487#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7488 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7489 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7490#else
7491 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7492 {
7493 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7494 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7495 }
7496 else
7497 {
7498 /*
7499 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7500 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7501 * re-construct CR0. See @bugref{9180#c95} for details.
7502 */
7503 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7504 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7505 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7506 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7507 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7508 }
7509#endif
7510 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7511 CPUMSetGuestCR0(pVCpu, u64Cr0);
7512 VMMRZCallRing3Enable(pVCpu);
7513 }
7514
7515 if (fWhat & CPUMCTX_EXTRN_CR4)
7516 {
7517 uint64_t u64Cr4;
7518 uint64_t u64Shadow;
7519 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7520 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7521#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7522 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7523 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7524#else
7525 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7526 {
7527 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7528 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7529 }
7530 else
7531 {
7532 /*
7533 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7534 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7535 * re-construct CR4. See @bugref{9180#c95} for details.
7536 */
7537 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7538 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7539 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7540 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7541 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7542 }
7543#endif
7544 pCtx->cr4 = u64Cr4;
7545 }
7546
7547 if (fWhat & CPUMCTX_EXTRN_CR3)
7548 {
7549 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7550 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7551 || ( pVM->hm.s.fNestedPaging
7552 && CPUMIsGuestPagingEnabledEx(pCtx)))
7553 {
7554 uint64_t u64Cr3;
7555 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7556 if (pCtx->cr3 != u64Cr3)
7557 {
7558 pCtx->cr3 = u64Cr3;
7559 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7560 }
7561
7562 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7563 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7564 if (CPUMIsGuestInPAEModeEx(pCtx))
7565 {
7566 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7567 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7568 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7569 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7570 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7571 }
7572 }
7573 }
7574 }
7575
7576#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7577 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7578 {
7579 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7580 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7581 {
7582 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7583 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7584 if (RT_SUCCESS(rc))
7585 { /* likely */ }
7586 else
7587 break;
7588 }
7589 }
7590#endif
7591 } while (0);
7592
7593 if (RT_SUCCESS(rc))
7594 {
7595 /* Update fExtrn. */
7596 pCtx->fExtrn &= ~fWhat;
7597
7598 /* If everything has been imported, clear the HM keeper bit. */
7599 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7600 {
7601 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7602 Assert(!pCtx->fExtrn);
7603 }
7604 }
7605 }
7606 else
7607 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7608
7609 /*
7610 * Restore interrupts.
7611 */
7612 ASMSetFlags(fEFlags);
7613
7614 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7615
7616 if (RT_SUCCESS(rc))
7617 { /* likely */ }
7618 else
7619 return rc;
7620
7621 /*
7622 * Honor any pending CR3 updates.
7623 *
7624 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7625 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7626 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7627 *
7628 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7629 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7630 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7631 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7632 *
7633 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7634 */
7635 if (VMMRZCallRing3IsEnabled(pVCpu))
7636 {
7637 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7638 {
7639 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7640 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7641 }
7642
7643 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7644 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7645
7646 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7647 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7648 }
7649
7650 return VINF_SUCCESS;
7651}
7652
7653
7654/**
7655 * Saves the guest state from the VMCS into the guest-CPU context.
7656 *
7657 * @returns VBox status code.
7658 * @param pVCpu The cross context virtual CPU structure.
7659 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7660 */
7661VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7662{
7663 AssertPtr(pVCpu);
7664 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7665 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7666}
7667
7668
7669/**
7670 * Check per-VM and per-VCPU force flag actions that require us to go back to
7671 * ring-3 for one reason or another.
7672 *
7673 * @returns Strict VBox status code (i.e. informational status codes too)
7674 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7675 * ring-3.
7676 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7677 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7678 * interrupts)
7679 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7680 * all EMTs to be in ring-3.
7681 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7682 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7683 * to the EM loop.
7684 *
7685 * @param pVCpu The cross context virtual CPU structure.
7686 * @param fStepping Whether we are single-stepping the guest using the
7687 * hypervisor debugger.
7688 *
7689 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7690 * is no longer in VMX non-root mode.
7691 */
7692static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, bool fStepping)
7693{
7694 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7695
7696 /*
7697 * Update pending interrupts into the APIC's IRR.
7698 */
7699 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7700 APICUpdatePendingInterrupts(pVCpu);
7701
7702 /*
7703 * Anything pending? Should be more likely than not if we're doing a good job.
7704 */
7705 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7706 if ( !fStepping
7707 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7708 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7709 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7710 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7711 return VINF_SUCCESS;
7712
7713 /* Pending PGM C3 sync. */
7714 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7715 {
7716 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7717 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7718 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7719 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7720 if (rcStrict != VINF_SUCCESS)
7721 {
7722 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7723 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7724 return rcStrict;
7725 }
7726 }
7727
7728 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7729 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7730 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7731 {
7732 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7733 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7734 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7735 return rc;
7736 }
7737
7738 /* Pending VM request packets, such as hardware interrupts. */
7739 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7740 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7741 {
7742 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7743 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7744 return VINF_EM_PENDING_REQUEST;
7745 }
7746
7747 /* Pending PGM pool flushes. */
7748 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7749 {
7750 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7751 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7752 return VINF_PGM_POOL_FLUSH_PENDING;
7753 }
7754
7755 /* Pending DMA requests. */
7756 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7757 {
7758 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7759 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7760 return VINF_EM_RAW_TO_R3;
7761 }
7762
7763#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7764 /* Pending nested-guest APIC-write (has highest priority among nested-guest FFs). */
7765 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7766 {
7767 Log4Func(("Pending nested-guest APIC-write\n"));
7768 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7769 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7770 return rcStrict;
7771 }
7772 /** @todo VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_PREEMPT_TIMER */
7773#endif
7774
7775 return VINF_SUCCESS;
7776}
7777
7778
7779/**
7780 * Converts any TRPM trap into a pending HM event. This is typically used when
7781 * entering from ring-3 (not longjmp returns).
7782 *
7783 * @param pVCpu The cross context virtual CPU structure.
7784 */
7785static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7786{
7787 Assert(TRPMHasTrap(pVCpu));
7788 Assert(!pVCpu->hm.s.Event.fPending);
7789
7790 uint8_t uVector;
7791 TRPMEVENT enmTrpmEvent;
7792 RTGCUINT uErrCode;
7793 RTGCUINTPTR GCPtrFaultAddress;
7794 uint8_t cbInstr;
7795
7796 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
7797 AssertRC(rc);
7798
7799 uint32_t u32IntInfo;
7800 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7801 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
7802
7803 rc = TRPMResetTrap(pVCpu);
7804 AssertRC(rc);
7805 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7806 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7807
7808 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7809}
7810
7811
7812/**
7813 * Converts the pending HM event into a TRPM trap.
7814 *
7815 * @param pVCpu The cross context virtual CPU structure.
7816 */
7817static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7818{
7819 Assert(pVCpu->hm.s.Event.fPending);
7820
7821 /* If a trap was already pending, we did something wrong! */
7822 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7823
7824 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7825 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7826 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7827
7828 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7829
7830 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7831 AssertRC(rc);
7832
7833 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7834 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7835
7836 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7837 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7838 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7839 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7840
7841 /* We're now done converting the pending event. */
7842 pVCpu->hm.s.Event.fPending = false;
7843}
7844
7845
7846/**
7847 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7848 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7849 *
7850 * @param pVCpu The cross context virtual CPU structure.
7851 * @param pVmcsInfo The VMCS info. object.
7852 */
7853static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7854{
7855 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7856 {
7857 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7858 {
7859 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7860 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7861 AssertRC(rc);
7862 }
7863 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7864}
7865
7866
7867/**
7868 * Clears the interrupt-window exiting control in the VMCS.
7869 *
7870 * @param pVmcsInfo The VMCS info. object.
7871 */
7872DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7873{
7874 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7875 {
7876 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7877 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7878 AssertRC(rc);
7879 }
7880}
7881
7882
7883/**
7884 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7885 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7886 *
7887 * @param pVCpu The cross context virtual CPU structure.
7888 * @param pVmcsInfo The VMCS info. object.
7889 */
7890static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7891{
7892 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7893 {
7894 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7895 {
7896 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7897 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7898 AssertRC(rc);
7899 Log4Func(("Setup NMI-window exiting\n"));
7900 }
7901 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7902}
7903
7904
7905/**
7906 * Clears the NMI-window exiting control in the VMCS.
7907 *
7908 * @param pVmcsInfo The VMCS info. object.
7909 */
7910DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7911{
7912 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7913 {
7914 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7915 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7916 AssertRC(rc);
7917 }
7918}
7919
7920
7921/**
7922 * Does the necessary state syncing before returning to ring-3 for any reason
7923 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7924 *
7925 * @returns VBox status code.
7926 * @param pVCpu The cross context virtual CPU structure.
7927 * @param fImportState Whether to import the guest state from the VMCS back
7928 * to the guest-CPU context.
7929 *
7930 * @remarks No-long-jmp zone!!!
7931 */
7932static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7933{
7934 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7935 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7936
7937 RTCPUID const idCpu = RTMpCpuId();
7938 Log4Func(("HostCpuId=%u\n", idCpu));
7939
7940 /*
7941 * !!! IMPORTANT !!!
7942 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
7943 */
7944
7945 /* Save the guest state if necessary. */
7946 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7947 if (fImportState)
7948 {
7949 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7950 AssertRCReturn(rc, rc);
7951 }
7952
7953 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7954 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7955 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7956
7957 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7958#ifdef VBOX_STRICT
7959 if (CPUMIsHyperDebugStateActive(pVCpu))
7960 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7961#endif
7962 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7963 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7964 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7965
7966 /* Restore host-state bits that VT-x only restores partially. */
7967 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7968 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7969 {
7970 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7971 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7972 }
7973 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7974
7975 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7976 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7977 {
7978 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7979 if (!fImportState)
7980 {
7981 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7982 AssertRCReturn(rc, rc);
7983 }
7984 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7985 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7986 }
7987 else
7988 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7989
7990 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7991 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7992
7993 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7994 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7995 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7996 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7997 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7998 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7999 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8000 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8001 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8002 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8003
8004 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8005
8006 /** @todo This partially defeats the purpose of having preemption hooks.
8007 * The problem is, deregistering the hooks should be moved to a place that
8008 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8009 * context.
8010 */
8011 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8012 AssertRCReturn(rc, rc);
8013
8014#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8015 /*
8016 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8017 * clear a shadow VMCS before allowing that VMCS to become active on another
8018 * logical processor. We may or may not be importing guest state which clears
8019 * it, so cover for it here.
8020 *
8021 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8022 */
8023 if ( pVmcsInfo->pvShadowVmcs
8024 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8025 {
8026 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8027 AssertRCReturn(rc, rc);
8028 }
8029
8030 /*
8031 * Flag that we need to re-export the host state if we switch to this VMCS before
8032 * executing guest or nested-guest code.
8033 */
8034 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8035#endif
8036
8037 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8038 NOREF(idCpu);
8039 return VINF_SUCCESS;
8040}
8041
8042
8043/**
8044 * Leaves the VT-x session.
8045 *
8046 * @returns VBox status code.
8047 * @param pVCpu The cross context virtual CPU structure.
8048 *
8049 * @remarks No-long-jmp zone!!!
8050 */
8051static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8052{
8053 HM_DISABLE_PREEMPT(pVCpu);
8054 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8055 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8056 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8057
8058 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8059 and done this from the VMXR0ThreadCtxCallback(). */
8060 if (!pVCpu->hm.s.fLeaveDone)
8061 {
8062 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8063 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8064 pVCpu->hm.s.fLeaveDone = true;
8065 }
8066 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8067
8068 /*
8069 * !!! IMPORTANT !!!
8070 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8071 */
8072
8073 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8074 /** @todo Deregistering here means we need to VMCLEAR always
8075 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8076 * for calling VMMR0ThreadCtxHookDisable here! */
8077 VMMR0ThreadCtxHookDisable(pVCpu);
8078
8079 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8080 int rc = HMR0LeaveCpu(pVCpu);
8081 HM_RESTORE_PREEMPT();
8082 return rc;
8083}
8084
8085
8086/**
8087 * Does the necessary state syncing before doing a longjmp to ring-3.
8088 *
8089 * @returns VBox status code.
8090 * @param pVCpu The cross context virtual CPU structure.
8091 *
8092 * @remarks No-long-jmp zone!!!
8093 */
8094DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8095{
8096 return hmR0VmxLeaveSession(pVCpu);
8097}
8098
8099
8100/**
8101 * Take necessary actions before going back to ring-3.
8102 *
8103 * An action requires us to go back to ring-3. This function does the necessary
8104 * steps before we can safely return to ring-3. This is not the same as longjmps
8105 * to ring-3, this is voluntary and prepares the guest so it may continue
8106 * executing outside HM (recompiler/IEM).
8107 *
8108 * @returns VBox status code.
8109 * @param pVCpu The cross context virtual CPU structure.
8110 * @param rcExit The reason for exiting to ring-3. Can be
8111 * VINF_VMM_UNKNOWN_RING3_CALL.
8112 */
8113static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8114{
8115 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8116
8117 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8118 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8119 {
8120 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8121 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8122 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8123 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8124 }
8125
8126 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8127 VMMRZCallRing3Disable(pVCpu);
8128 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8129
8130 /*
8131 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8132 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8133 *
8134 * This is because execution may continue from ring-3 and we would need to inject
8135 * the event from there (hence place it back in TRPM).
8136 */
8137 if (pVCpu->hm.s.Event.fPending)
8138 {
8139 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8140 Assert(!pVCpu->hm.s.Event.fPending);
8141
8142 /* Clear the events from the VMCS. */
8143 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8144 AssertRC(rc);
8145 }
8146#ifdef VBOX_STRICT
8147 else
8148 {
8149 /*
8150 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8151 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8152 * occasionally, see @bugref{9180#c42}.
8153 *
8154 * However, if the VM-entry failed, any VM entry-interruption info. field would
8155 * be left unmodified as the event would not have been injected to the guest. In
8156 * such cases, don't assert, we're not going to continue guest execution anyway.
8157 */
8158 uint32_t uExitReason;
8159 uint32_t uEntryIntInfo;
8160 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8161 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8162 AssertRC(rc);
8163 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8164 }
8165#endif
8166
8167 /*
8168 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8169 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8170 * (e.g. TPR below threshold).
8171 */
8172 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8173 {
8174 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8175 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8176 }
8177
8178 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8179 and if we're injecting an event we should have a TRPM trap pending. */
8180 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8181#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8182 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8183#endif
8184
8185 /* Save guest state and restore host state bits. */
8186 int rc = hmR0VmxLeaveSession(pVCpu);
8187 AssertRCReturn(rc, rc);
8188 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8189
8190 /* Thread-context hooks are unregistered at this point!!! */
8191 /* Ring-3 callback notifications are unregistered at this point!!! */
8192
8193 /* Sync recompiler state. */
8194 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8195 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8196 | CPUM_CHANGED_LDTR
8197 | CPUM_CHANGED_GDTR
8198 | CPUM_CHANGED_IDTR
8199 | CPUM_CHANGED_TR
8200 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8201 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8202 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8203 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8204
8205 Assert(!pVCpu->hm.s.fClearTrapFlag);
8206
8207 /* Update the exit-to-ring 3 reason. */
8208 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8209
8210 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8211 if ( rcExit != VINF_EM_RAW_INTERRUPT
8212 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8213 {
8214 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8215 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8216 }
8217
8218 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8219 VMMRZCallRing3Enable(pVCpu);
8220 return rc;
8221}
8222
8223
8224/**
8225 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8226 * longjump to ring-3 and possibly get preempted.
8227 *
8228 * @returns VBox status code.
8229 * @param pVCpu The cross context virtual CPU structure.
8230 * @param enmOperation The operation causing the ring-3 longjump.
8231 */
8232VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8233{
8234 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8235 {
8236 /*
8237 * !!! IMPORTANT !!!
8238 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8239 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8240 */
8241 VMMRZCallRing3RemoveNotification(pVCpu);
8242 VMMRZCallRing3Disable(pVCpu);
8243 HM_DISABLE_PREEMPT(pVCpu);
8244
8245 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8246 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8247 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8248 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8249
8250 /* Restore host-state bits that VT-x only restores partially. */
8251 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8252 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8253 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8254 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8255
8256 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8257 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8258 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8259
8260 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8261 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8262 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8263
8264 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8265 cleared as part of importing the guest state above. */
8266 hmR0VmxClearVmcs(pVmcsInfo);
8267
8268 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8269 VMMR0ThreadCtxHookDisable(pVCpu);
8270
8271 /* Leave HM context. This takes care of local init (term). */
8272 HMR0LeaveCpu(pVCpu);
8273 HM_RESTORE_PREEMPT();
8274 return VINF_SUCCESS;
8275 }
8276
8277 Assert(pVCpu);
8278 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8279 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8280
8281 VMMRZCallRing3Disable(pVCpu);
8282 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8283
8284 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8285
8286 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8287 AssertRCReturn(rc, rc);
8288
8289 VMMRZCallRing3Enable(pVCpu);
8290 return VINF_SUCCESS;
8291}
8292
8293
8294/**
8295 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8296 * stack.
8297 *
8298 * @returns Strict VBox status code (i.e. informational status codes too).
8299 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8300 * @param pVCpu The cross context virtual CPU structure.
8301 * @param uValue The value to push to the guest stack.
8302 */
8303static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8304{
8305 /*
8306 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8307 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8308 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8309 */
8310 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8311 if (pCtx->sp == 1)
8312 return VINF_EM_RESET;
8313 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8314 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8315 AssertRC(rc);
8316 return rc;
8317}
8318
8319
8320/**
8321 * Injects an event into the guest upon VM-entry by updating the relevant fields
8322 * in the VM-entry area in the VMCS.
8323 *
8324 * @returns Strict VBox status code (i.e. informational status codes too).
8325 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8326 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8327 *
8328 * @param pVCpu The cross context virtual CPU structure.
8329 * @param pVmxTransient The VMX-transient structure.
8330 * @param pEvent The event being injected.
8331 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8332 * will be updated if necessary. This cannot not be NULL.
8333 * @param fStepping Whether we're single-stepping guest execution and should
8334 * return VINF_EM_DBG_STEPPED if the event is injected
8335 * directly (registers modified by us, not by hardware on
8336 * VM-entry).
8337 */
8338static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8339 uint32_t *pfIntrState)
8340{
8341 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8342 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8343 Assert(pfIntrState);
8344
8345 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8346 uint32_t u32IntInfo = pEvent->u64IntInfo;
8347 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8348 uint32_t const cbInstr = pEvent->cbInstr;
8349 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8350 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8351 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8352
8353#ifdef VBOX_STRICT
8354 /*
8355 * Validate the error-code-valid bit for hardware exceptions.
8356 * No error codes for exceptions in real-mode.
8357 *
8358 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8359 */
8360 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8361 && !CPUMIsGuestInRealModeEx(pCtx))
8362 {
8363 switch (uVector)
8364 {
8365 case X86_XCPT_PF:
8366 case X86_XCPT_DF:
8367 case X86_XCPT_TS:
8368 case X86_XCPT_NP:
8369 case X86_XCPT_SS:
8370 case X86_XCPT_GP:
8371 case X86_XCPT_AC:
8372 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8373 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8374 RT_FALL_THRU();
8375 default:
8376 break;
8377 }
8378 }
8379
8380 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8381 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8382 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8383#endif
8384
8385 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8386
8387 /*
8388 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8389 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8390 * interrupt handler in the (real-mode) guest.
8391 *
8392 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8393 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8394 */
8395 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8396 {
8397 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8398 {
8399 /*
8400 * For CPUs with unrestricted guest execution enabled and with the guest
8401 * in real-mode, we must not set the deliver-error-code bit.
8402 *
8403 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8404 */
8405 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8406 }
8407 else
8408 {
8409 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8410 Assert(PDMVmmDevHeapIsEnabled(pVM));
8411 Assert(pVM->hm.s.vmx.pRealModeTSS);
8412 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8413
8414 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8415 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8416 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8417 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8418 AssertRCReturn(rc2, rc2);
8419
8420 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8421 size_t const cbIdtEntry = sizeof(X86IDTR16);
8422 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8423 {
8424 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8425 if (uVector == X86_XCPT_DF)
8426 return VINF_EM_RESET;
8427
8428 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8429 No error codes for exceptions in real-mode. */
8430 if (uVector == X86_XCPT_GP)
8431 {
8432 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8433 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8434 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8435 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8436 HMEVENT EventXcptDf;
8437 RT_ZERO(EventXcptDf);
8438 EventXcptDf.u64IntInfo = uXcptDfInfo;
8439 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8440 }
8441
8442 /*
8443 * If we're injecting an event with no valid IDT entry, inject a #GP.
8444 * No error codes for exceptions in real-mode.
8445 *
8446 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8447 */
8448 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8449 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8450 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8451 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8452 HMEVENT EventXcptGp;
8453 RT_ZERO(EventXcptGp);
8454 EventXcptGp.u64IntInfo = uXcptGpInfo;
8455 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8456 }
8457
8458 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8459 uint16_t uGuestIp = pCtx->ip;
8460 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8461 {
8462 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8463 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8464 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8465 }
8466 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8467 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8468
8469 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8470 X86IDTR16 IdtEntry;
8471 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8472 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8473 AssertRCReturn(rc2, rc2);
8474
8475 /* Construct the stack frame for the interrupt/exception handler. */
8476 VBOXSTRICTRC rcStrict;
8477 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8478 if (rcStrict == VINF_SUCCESS)
8479 {
8480 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8481 if (rcStrict == VINF_SUCCESS)
8482 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8483 }
8484
8485 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8486 if (rcStrict == VINF_SUCCESS)
8487 {
8488 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8489 pCtx->rip = IdtEntry.offSel;
8490 pCtx->cs.Sel = IdtEntry.uSel;
8491 pCtx->cs.ValidSel = IdtEntry.uSel;
8492 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8493 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8494 && uVector == X86_XCPT_PF)
8495 pCtx->cr2 = GCPtrFault;
8496
8497 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8498 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8499 | HM_CHANGED_GUEST_RSP);
8500
8501 /*
8502 * If we delivered a hardware exception (other than an NMI) and if there was
8503 * block-by-STI in effect, we should clear it.
8504 */
8505 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8506 {
8507 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8508 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8509 Log4Func(("Clearing inhibition due to STI\n"));
8510 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8511 }
8512
8513 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8514 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8515
8516 /*
8517 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8518 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8519 */
8520 pVCpu->hm.s.Event.fPending = false;
8521
8522 /*
8523 * If we eventually support nested-guest execution without unrestricted guest execution,
8524 * we should set fInterceptEvents here.
8525 */
8526 Assert(!pVmxTransient->fIsNestedGuest);
8527
8528 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8529 if (fStepping)
8530 rcStrict = VINF_EM_DBG_STEPPED;
8531 }
8532 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8533 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8534 return rcStrict;
8535 }
8536 }
8537
8538 /*
8539 * Validate.
8540 */
8541 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8542 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8543
8544 /*
8545 * Inject the event into the VMCS.
8546 */
8547 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8548 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8549 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8550 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8551 AssertRC(rc);
8552
8553 /*
8554 * Update guest CR2 if this is a page-fault.
8555 */
8556 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8557 pCtx->cr2 = GCPtrFault;
8558
8559 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8560 return VINF_SUCCESS;
8561}
8562
8563
8564/**
8565 * Evaluates the event to be delivered to the guest and sets it as the pending
8566 * event.
8567 *
8568 * @returns Strict VBox status code (i.e. informational status codes too).
8569 * @param pVCpu The cross context virtual CPU structure.
8570 * @param pVmxTransient The VMX-transient structure.
8571 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8572 */
8573static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8574{
8575 Assert(pfIntrState);
8576 Assert(!TRPMHasTrap(pVCpu));
8577
8578 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8579 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8580 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8581
8582 /*
8583 * Get the current interruptibility-state of the guest or nested-guest and
8584 * then figure out what needs to be injected.
8585 */
8586 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8587 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8588 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8589 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8590
8591 /* We don't support block-by-SMI yet.*/
8592 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8593
8594 /* Block-by-STI must not be set when interrupts are disabled. */
8595 if (fBlockSti)
8596 {
8597 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8598 Assert(pCtx->eflags.Bits.u1IF);
8599 }
8600
8601 /* Update interruptibility state to the caller. */
8602 *pfIntrState = fIntrState;
8603
8604 /*
8605 * Toggling of interrupt force-flags here is safe since we update TRPM on
8606 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8607 * We must NOT restore these force-flags.
8608 */
8609
8610 /** @todo SMI. SMIs take priority over NMIs. */
8611
8612 /*
8613 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8614 * NMIs take priority over external interrupts.
8615 */
8616 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8617 {
8618 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8619 if ( !pVCpu->hm.s.Event.fPending
8620 && !fBlockNmi
8621 && !fBlockSti
8622 && !fBlockMovSS)
8623 {
8624#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8625 if ( fIsNestedGuest
8626 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8627 return IEMExecVmxVmexitXcptNmi(pVCpu);
8628#endif
8629 hmR0VmxSetPendingXcptNmi(pVCpu);
8630 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8631 Log4Func(("Pending NMI\n"));
8632 }
8633 else if (!fIsNestedGuest)
8634 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8635 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8636 }
8637 /*
8638 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8639 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8640 * the interrupt. We can no longer re-request it from the APIC.
8641 */
8642 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8643 && !pVCpu->hm.s.fSingleInstruction)
8644 {
8645 Assert(!DBGFIsStepping(pVCpu));
8646 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8647 AssertRCReturn(rc, rc);
8648
8649 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8650 if ( !pVCpu->hm.s.Event.fPending
8651 && !fBlockInt
8652 && !fBlockSti
8653 && !fBlockMovSS)
8654 {
8655#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8656 if ( fIsNestedGuest
8657 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8658 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8659 {
8660 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8661 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8662 return rcStrict;
8663 }
8664#endif
8665 uint8_t u8Interrupt;
8666 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8667 if (RT_SUCCESS(rc))
8668 {
8669#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8670 if ( fIsNestedGuest
8671 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8672 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8673 {
8674 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8675 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8676 return rcStrict;
8677 }
8678#endif
8679 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8680 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8681 }
8682 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8683 {
8684 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8685
8686 if ( !fIsNestedGuest
8687 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8688 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8689 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8690
8691 /*
8692 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8693 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8694 * need to re-set this force-flag here.
8695 */
8696 }
8697 else
8698 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8699 }
8700 else if (!fIsNestedGuest)
8701 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8702 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8703 }
8704
8705 return VINF_SUCCESS;
8706}
8707
8708
8709/**
8710 * Injects any pending events into the guest if the guest is in a state to
8711 * receive them.
8712 *
8713 * @returns Strict VBox status code (i.e. informational status codes too).
8714 * @param pVCpu The cross context virtual CPU structure.
8715 * @param pVmxTransient The VMX-transient structure.
8716 * @param fIntrState The VT-x guest-interruptibility state.
8717 * @param fStepping Whether we are single-stepping the guest using the
8718 * hypervisor debugger and should return
8719 * VINF_EM_DBG_STEPPED if the event was dispatched
8720 * directly.
8721 */
8722static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8723{
8724 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8725 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8726
8727 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8728 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8729
8730 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8731 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8732 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8733 Assert(!TRPMHasTrap(pVCpu));
8734
8735 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8736 if (pVCpu->hm.s.Event.fPending)
8737 {
8738 /*
8739 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8740 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8741 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8742 *
8743 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8744 */
8745 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8746#ifdef VBOX_STRICT
8747 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8748 {
8749 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8750 Assert(!fBlockInt);
8751 Assert(!fBlockSti);
8752 Assert(!fBlockMovSS);
8753 }
8754 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8755 {
8756 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8757 Assert(!fBlockSti);
8758 Assert(!fBlockMovSS);
8759 Assert(!fBlockNmi);
8760 }
8761#endif
8762 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8763 uIntType));
8764
8765 /*
8766 * Inject the event and get any changes to the guest-interruptibility state.
8767 *
8768 * The guest-interruptibility state may need to be updated if we inject the event
8769 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8770 */
8771 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8772 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8773
8774 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8775 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8776 else
8777 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8778 }
8779
8780 /*
8781 * Update the guest-interruptibility state.
8782 *
8783 * This is required for the real-on-v86 software interrupt injection case above, as well as
8784 * updates to the guest state from ring-3 or IEM/REM.
8785 */
8786 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8787 AssertRC(rc);
8788
8789 /*
8790 * There's no need to clear the VM-entry interruption-information field here if we're not
8791 * injecting anything. VT-x clears the valid bit on every VM-exit.
8792 *
8793 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8794 */
8795
8796 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8797 NOREF(fBlockMovSS); NOREF(fBlockSti);
8798 return rcStrict;
8799}
8800
8801
8802/**
8803 * Enters the VT-x session.
8804 *
8805 * @returns VBox status code.
8806 * @param pVCpu The cross context virtual CPU structure.
8807 */
8808VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8809{
8810 AssertPtr(pVCpu);
8811 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8812 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8813
8814 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8815 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8816 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8817
8818#ifdef VBOX_STRICT
8819 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8820 RTCCUINTREG uHostCr4 = ASMGetCR4();
8821 if (!(uHostCr4 & X86_CR4_VMXE))
8822 {
8823 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8824 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8825 }
8826#endif
8827
8828 /*
8829 * Load the appropriate VMCS as the current and active one.
8830 */
8831 PVMXVMCSINFO pVmcsInfo;
8832 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8833 if (!fInNestedGuestMode)
8834 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8835 else
8836 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8837 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8838 if (RT_SUCCESS(rc))
8839 {
8840 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8841 pVCpu->hm.s.fLeaveDone = false;
8842 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8843
8844 /*
8845 * Do the EMT scheduled L1D flush here if needed.
8846 */
8847 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8848 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8849 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8850 hmR0MdsClear();
8851 }
8852 return rc;
8853}
8854
8855
8856/**
8857 * The thread-context callback (only on platforms which support it).
8858 *
8859 * @param enmEvent The thread-context event.
8860 * @param pVCpu The cross context virtual CPU structure.
8861 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8862 * @thread EMT(pVCpu)
8863 */
8864VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8865{
8866 AssertPtr(pVCpu);
8867 RT_NOREF1(fGlobalInit);
8868
8869 switch (enmEvent)
8870 {
8871 case RTTHREADCTXEVENT_OUT:
8872 {
8873 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8874 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8875 VMCPU_ASSERT_EMT(pVCpu);
8876
8877 /* No longjmps (logger flushes, locks) in this fragile context. */
8878 VMMRZCallRing3Disable(pVCpu);
8879 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8880
8881 /* Restore host-state (FPU, debug etc.) */
8882 if (!pVCpu->hm.s.fLeaveDone)
8883 {
8884 /*
8885 * Do -not- import the guest-state here as we might already be in the middle of importing
8886 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8887 */
8888 hmR0VmxLeave(pVCpu, false /* fImportState */);
8889 pVCpu->hm.s.fLeaveDone = true;
8890 }
8891
8892 /* Leave HM context, takes care of local init (term). */
8893 int rc = HMR0LeaveCpu(pVCpu);
8894 AssertRC(rc);
8895
8896 /* Restore longjmp state. */
8897 VMMRZCallRing3Enable(pVCpu);
8898 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8899 break;
8900 }
8901
8902 case RTTHREADCTXEVENT_IN:
8903 {
8904 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8905 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8906 VMCPU_ASSERT_EMT(pVCpu);
8907
8908 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8909 VMMRZCallRing3Disable(pVCpu);
8910 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8911
8912 /* Initialize the bare minimum state required for HM. This takes care of
8913 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8914 int rc = hmR0EnterCpu(pVCpu);
8915 AssertRC(rc);
8916 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8917 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8918
8919 /* Load the active VMCS as the current one. */
8920 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8921 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8922 AssertRC(rc);
8923 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8924 pVCpu->hm.s.fLeaveDone = false;
8925
8926 /* Do the EMT scheduled L1D flush if needed. */
8927 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8928 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8929
8930 /* Restore longjmp state. */
8931 VMMRZCallRing3Enable(pVCpu);
8932 break;
8933 }
8934
8935 default:
8936 break;
8937 }
8938}
8939
8940
8941/**
8942 * Exports the host state into the VMCS host-state area.
8943 * Sets up the VM-exit MSR-load area.
8944 *
8945 * The CPU state will be loaded from these fields on every successful VM-exit.
8946 *
8947 * @returns VBox status code.
8948 * @param pVCpu The cross context virtual CPU structure.
8949 *
8950 * @remarks No-long-jump zone!!!
8951 */
8952static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
8953{
8954 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8955
8956 int rc = VINF_SUCCESS;
8957 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8958 {
8959 hmR0VmxExportHostControlRegs();
8960
8961 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8962 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8963
8964 hmR0VmxExportHostMsrs(pVCpu);
8965
8966 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8967 }
8968 return rc;
8969}
8970
8971
8972/**
8973 * Saves the host state in the VMCS host-state.
8974 *
8975 * @returns VBox status code.
8976 * @param pVCpu The cross context virtual CPU structure.
8977 *
8978 * @remarks No-long-jump zone!!!
8979 */
8980VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
8981{
8982 AssertPtr(pVCpu);
8983 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8984
8985 /*
8986 * Export the host state here while entering HM context.
8987 * When thread-context hooks are used, we might get preempted and have to re-save the host
8988 * state but most of the time we won't be, so do it here before we disable interrupts.
8989 */
8990 return hmR0VmxExportHostState(pVCpu);
8991}
8992
8993
8994/**
8995 * Exports the guest state into the VMCS guest-state area.
8996 *
8997 * The will typically be done before VM-entry when the guest-CPU state and the
8998 * VMCS state may potentially be out of sync.
8999 *
9000 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9001 * VM-entry controls.
9002 * Sets up the appropriate VMX non-root function to execute guest code based on
9003 * the guest CPU mode.
9004 *
9005 * @returns VBox strict status code.
9006 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9007 * without unrestricted guest execution and the VMMDev is not presently
9008 * mapped (e.g. EFI32).
9009 *
9010 * @param pVCpu The cross context virtual CPU structure.
9011 * @param pVmxTransient The VMX-transient structure.
9012 *
9013 * @remarks No-long-jump zone!!!
9014 */
9015static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9016{
9017 AssertPtr(pVCpu);
9018 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9019 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9020
9021 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9022
9023 /*
9024 * Determine real-on-v86 mode.
9025 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9026 */
9027 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9028 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9029 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9030 pVmcsInfo->RealMode. fRealOnV86Active = false;
9031 else
9032 {
9033 Assert(!pVmxTransient->fIsNestedGuest);
9034 pVmcsInfo->RealMode.fRealOnV86Active = true;
9035 }
9036
9037 /*
9038 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9039 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9040 */
9041 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9042 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9043 * be a need to evaluate this everytime since I'm pretty sure we intercept
9044 * all guest paging mode changes. */
9045 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9046 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9047
9048 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9049 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9050
9051 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9052 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9053
9054 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9055 if (rcStrict == VINF_SUCCESS)
9056 { /* likely */ }
9057 else
9058 {
9059 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9060 return rcStrict;
9061 }
9062
9063 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9064 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9065
9066 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9067 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9068
9069 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9070 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9071
9072 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9073 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9074
9075 rc = hmR0VmxExportGuestRip(pVCpu);
9076 rc |= hmR0VmxExportGuestRsp(pVCpu);
9077 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9078 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9079
9080 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9081 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9082
9083 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9084 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9085 | HM_CHANGED_GUEST_CR2
9086 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9087 | HM_CHANGED_GUEST_X87
9088 | HM_CHANGED_GUEST_SSE_AVX
9089 | HM_CHANGED_GUEST_OTHER_XSAVE
9090 | HM_CHANGED_GUEST_XCRx
9091 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9092 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9093 | HM_CHANGED_GUEST_TSC_AUX
9094 | HM_CHANGED_GUEST_OTHER_MSRS
9095 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9096
9097 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9098 return rc;
9099}
9100
9101
9102/**
9103 * Exports the state shared between the host and guest into the VMCS.
9104 *
9105 * @param pVCpu The cross context virtual CPU structure.
9106 * @param pVmxTransient The VMX-transient structure.
9107 *
9108 * @remarks No-long-jump zone!!!
9109 */
9110static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9111{
9112 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9113 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9114
9115 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9116 {
9117 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9118 AssertRC(rc);
9119 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9120
9121 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9122 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9123 {
9124 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9125 AssertRC(rc);
9126 }
9127 }
9128
9129 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9130 {
9131 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9132 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9133 }
9134
9135 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9136 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9137}
9138
9139
9140/**
9141 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9142 *
9143 * @returns Strict VBox status code (i.e. informational status codes too).
9144 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9145 * without unrestricted guest execution and the VMMDev is not presently
9146 * mapped (e.g. EFI32).
9147 *
9148 * @param pVCpu The cross context virtual CPU structure.
9149 * @param pVmxTransient The VMX-transient structure.
9150 *
9151 * @remarks No-long-jump zone!!!
9152 */
9153static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9154{
9155 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9156 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9157 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9158
9159#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9160 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9161#endif
9162
9163 /*
9164 * For many exits it's only RIP that changes and hence try to export it first
9165 * without going through a lot of change flag checks.
9166 */
9167 VBOXSTRICTRC rcStrict;
9168 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9169 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9170 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9171 {
9172 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9173 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9174 { /* likely */}
9175 else
9176 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9177 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9178 }
9179 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9180 {
9181 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9182 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9183 { /* likely */}
9184 else
9185 {
9186 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9187 VBOXSTRICTRC_VAL(rcStrict)));
9188 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9189 return rcStrict;
9190 }
9191 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9192 }
9193 else
9194 rcStrict = VINF_SUCCESS;
9195
9196#ifdef VBOX_STRICT
9197 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9198 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9199 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9200 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9201 ("fCtxChanged=%#RX64\n", fCtxChanged));
9202#endif
9203 return rcStrict;
9204}
9205
9206
9207/**
9208 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9209 * and update error record fields accordingly.
9210 *
9211 * @returns VMX_IGS_* error codes.
9212 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9213 * wrong with the guest state.
9214 *
9215 * @param pVCpu The cross context virtual CPU structure.
9216 * @param pVmcsInfo The VMCS info. object.
9217 *
9218 * @remarks This function assumes our cache of the VMCS controls
9219 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9220 */
9221static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9222{
9223#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9224#define HMVMX_CHECK_BREAK(expr, err) do { \
9225 if (!(expr)) { uError = (err); break; } \
9226 } while (0)
9227
9228 int rc;
9229 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9230 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9231 uint32_t uError = VMX_IGS_ERROR;
9232 uint32_t u32Val;
9233 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9234
9235 do
9236 {
9237 /*
9238 * CR0.
9239 */
9240 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9241 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9242 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9243 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9244 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9245 if (fUnrestrictedGuest)
9246 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9247
9248 uint64_t u64GuestCr0;
9249 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9250 AssertRC(rc);
9251 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9252 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9253 if ( !fUnrestrictedGuest
9254 && (u64GuestCr0 & X86_CR0_PG)
9255 && !(u64GuestCr0 & X86_CR0_PE))
9256 {
9257 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9258 }
9259
9260 /*
9261 * CR4.
9262 */
9263 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9264 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9265 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9266
9267 uint64_t u64GuestCr4;
9268 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9269 AssertRC(rc);
9270 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9271 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9272
9273 /*
9274 * IA32_DEBUGCTL MSR.
9275 */
9276 uint64_t u64Val;
9277 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9278 AssertRC(rc);
9279 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9280 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9281 {
9282 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9283 }
9284 uint64_t u64DebugCtlMsr = u64Val;
9285
9286#ifdef VBOX_STRICT
9287 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9288 AssertRC(rc);
9289 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9290#endif
9291 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9292
9293 /*
9294 * RIP and RFLAGS.
9295 */
9296 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9297 AssertRC(rc);
9298 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9299 if ( !fLongModeGuest
9300 || !pCtx->cs.Attr.n.u1Long)
9301 {
9302 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9303 }
9304 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9305 * must be identical if the "IA-32e mode guest" VM-entry
9306 * control is 1 and CS.L is 1. No check applies if the
9307 * CPU supports 64 linear-address bits. */
9308
9309 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9310 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9311 AssertRC(rc);
9312 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9313 VMX_IGS_RFLAGS_RESERVED);
9314 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9315 uint32_t const u32Eflags = u64Val;
9316
9317 if ( fLongModeGuest
9318 || ( fUnrestrictedGuest
9319 && !(u64GuestCr0 & X86_CR0_PE)))
9320 {
9321 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9322 }
9323
9324 uint32_t u32EntryInfo;
9325 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9326 AssertRC(rc);
9327 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9328 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9329
9330 /*
9331 * 64-bit checks.
9332 */
9333 if (fLongModeGuest)
9334 {
9335 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9336 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9337 }
9338
9339 if ( !fLongModeGuest
9340 && (u64GuestCr4 & X86_CR4_PCIDE))
9341 {
9342 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9343 }
9344
9345 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9346 * 51:32 beyond the processor's physical-address width are 0. */
9347
9348 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9349 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9350 {
9351 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9352 }
9353
9354 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9355 AssertRC(rc);
9356 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9357
9358 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9359 AssertRC(rc);
9360 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9361
9362 /*
9363 * PERF_GLOBAL MSR.
9364 */
9365 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9366 {
9367 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9368 AssertRC(rc);
9369 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9370 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9371 }
9372
9373 /*
9374 * PAT MSR.
9375 */
9376 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9377 {
9378 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9379 AssertRC(rc);
9380 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9381 for (unsigned i = 0; i < 8; i++)
9382 {
9383 uint8_t u8Val = (u64Val & 0xff);
9384 if ( u8Val != 0 /* UC */
9385 && u8Val != 1 /* WC */
9386 && u8Val != 4 /* WT */
9387 && u8Val != 5 /* WP */
9388 && u8Val != 6 /* WB */
9389 && u8Val != 7 /* UC- */)
9390 {
9391 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9392 }
9393 u64Val >>= 8;
9394 }
9395 }
9396
9397 /*
9398 * EFER MSR.
9399 */
9400 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9401 {
9402 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9403 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9404 AssertRC(rc);
9405 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9406 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9407 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9408 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9409 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9410 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9411 * iemVmxVmentryCheckGuestState(). */
9412 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9413 || !(u64GuestCr0 & X86_CR0_PG)
9414 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9415 VMX_IGS_EFER_LMA_LME_MISMATCH);
9416 }
9417
9418 /*
9419 * Segment registers.
9420 */
9421 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9422 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9423 if (!(u32Eflags & X86_EFL_VM))
9424 {
9425 /* CS */
9426 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9427 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9428 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9429 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9430 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9431 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9432 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9433 /* CS cannot be loaded with NULL in protected mode. */
9434 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9435 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9436 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9437 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9438 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9439 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9440 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9441 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9442 else
9443 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9444
9445 /* SS */
9446 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9447 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9448 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9449 if ( !(pCtx->cr0 & X86_CR0_PE)
9450 || pCtx->cs.Attr.n.u4Type == 3)
9451 {
9452 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9453 }
9454 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9455 {
9456 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9457 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9458 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9459 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9460 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9461 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9462 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9463 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9464 }
9465
9466 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9467 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9468 {
9469 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9470 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9471 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9472 || pCtx->ds.Attr.n.u4Type > 11
9473 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9474 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9475 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9476 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9477 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9478 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9479 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9480 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9481 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9482 }
9483 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9484 {
9485 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9486 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9487 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9488 || pCtx->es.Attr.n.u4Type > 11
9489 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9490 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9491 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9492 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9493 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9494 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9495 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9496 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9497 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9498 }
9499 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9500 {
9501 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9502 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9503 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9504 || pCtx->fs.Attr.n.u4Type > 11
9505 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9506 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9507 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9508 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9509 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9510 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9511 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9512 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9513 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9514 }
9515 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9516 {
9517 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9518 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9519 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9520 || pCtx->gs.Attr.n.u4Type > 11
9521 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9522 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9523 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9524 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9525 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9526 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9527 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9528 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9529 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9530 }
9531 /* 64-bit capable CPUs. */
9532 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9533 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9534 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9535 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9536 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9537 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9538 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9539 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9540 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9541 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9542 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9543 }
9544 else
9545 {
9546 /* V86 mode checks. */
9547 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9548 if (pVmcsInfo->RealMode.fRealOnV86Active)
9549 {
9550 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9551 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9552 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9553 }
9554 else
9555 {
9556 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9557 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9558 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9559 }
9560
9561 /* CS */
9562 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9563 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9564 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9565 /* SS */
9566 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9567 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9568 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9569 /* DS */
9570 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9571 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9572 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9573 /* ES */
9574 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9575 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9576 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9577 /* FS */
9578 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9579 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9580 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9581 /* GS */
9582 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9583 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9584 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9585 /* 64-bit capable CPUs. */
9586 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9587 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9588 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9589 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9590 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9591 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9592 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9593 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9594 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9595 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9596 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9597 }
9598
9599 /*
9600 * TR.
9601 */
9602 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9603 /* 64-bit capable CPUs. */
9604 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9605 if (fLongModeGuest)
9606 {
9607 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9608 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9609 }
9610 else
9611 {
9612 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9613 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9614 VMX_IGS_TR_ATTR_TYPE_INVALID);
9615 }
9616 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9617 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9618 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9619 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9620 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9621 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9622 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9623 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9624
9625 /*
9626 * GDTR and IDTR (64-bit capable checks).
9627 */
9628 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9629 AssertRC(rc);
9630 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9631
9632 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9633 AssertRC(rc);
9634 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9635
9636 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9637 AssertRC(rc);
9638 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9639
9640 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9641 AssertRC(rc);
9642 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9643
9644 /*
9645 * Guest Non-Register State.
9646 */
9647 /* Activity State. */
9648 uint32_t u32ActivityState;
9649 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9650 AssertRC(rc);
9651 HMVMX_CHECK_BREAK( !u32ActivityState
9652 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9653 VMX_IGS_ACTIVITY_STATE_INVALID);
9654 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9655 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9656 uint32_t u32IntrState;
9657 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9658 AssertRC(rc);
9659 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9660 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9661 {
9662 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9663 }
9664
9665 /** @todo Activity state and injecting interrupts. Left as a todo since we
9666 * currently don't use activity states but ACTIVE. */
9667
9668 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9669 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9670
9671 /* Guest interruptibility-state. */
9672 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9673 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9674 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9675 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9676 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9677 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9678 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9679 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9680 {
9681 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9682 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9683 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9684 }
9685 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9686 {
9687 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9688 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9689 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9690 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9691 }
9692 /** @todo Assumes the processor is not in SMM. */
9693 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9694 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9695 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9696 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9697 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9698 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9699 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9700 {
9701 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
9702 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9703 }
9704
9705 /* Pending debug exceptions. */
9706 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9707 AssertRC(rc);
9708 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9709 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9710 u32Val = u64Val; /* For pending debug exceptions checks below. */
9711
9712 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9713 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9714 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9715 {
9716 if ( (u32Eflags & X86_EFL_TF)
9717 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9718 {
9719 /* Bit 14 is PendingDebug.BS. */
9720 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9721 }
9722 if ( !(u32Eflags & X86_EFL_TF)
9723 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9724 {
9725 /* Bit 14 is PendingDebug.BS. */
9726 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9727 }
9728 }
9729
9730 /* VMCS link pointer. */
9731 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9732 AssertRC(rc);
9733 if (u64Val != UINT64_C(0xffffffffffffffff))
9734 {
9735 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9736 /** @todo Bits beyond the processor's physical-address width MBZ. */
9737 /** @todo SMM checks. */
9738 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9739 Assert(pVmcsInfo->pvShadowVmcs);
9740 VMXVMCSREVID VmcsRevId;
9741 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9742 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9743 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9744 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9745 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9746 }
9747
9748 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9749 * not using nested paging? */
9750 if ( pVM->hm.s.fNestedPaging
9751 && !fLongModeGuest
9752 && CPUMIsGuestInPAEModeEx(pCtx))
9753 {
9754 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9755 AssertRC(rc);
9756 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9757
9758 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9759 AssertRC(rc);
9760 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9761
9762 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9763 AssertRC(rc);
9764 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9765
9766 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9767 AssertRC(rc);
9768 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9769 }
9770
9771 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9772 if (uError == VMX_IGS_ERROR)
9773 uError = VMX_IGS_REASON_NOT_FOUND;
9774 } while (0);
9775
9776 pVCpu->hm.s.u32HMError = uError;
9777 return uError;
9778
9779#undef HMVMX_ERROR_BREAK
9780#undef HMVMX_CHECK_BREAK
9781}
9782
9783
9784/**
9785 * Map the APIC-access page for virtualizing APIC accesses.
9786 *
9787 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9788 * this not done as part of exporting guest state, see @bugref{8721}.
9789 *
9790 * @returns VBox status code.
9791 * @param pVCpu The cross context virtual CPU structure.
9792 */
9793static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9794{
9795 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9796 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9797
9798 Assert(PDMHasApic(pVM));
9799 Assert(u64MsrApicBase);
9800
9801 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9802 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9803
9804 /* Unalias the existing mapping. */
9805 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9806 AssertRCReturn(rc, rc);
9807
9808 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9809 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9810 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9811 AssertRCReturn(rc, rc);
9812
9813 /* Update the per-VCPU cache of the APIC base MSR. */
9814 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9815 return VINF_SUCCESS;
9816}
9817
9818
9819/**
9820 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9821 * CPU.
9822 *
9823 * @param idCpu The ID for the CPU the function is called on.
9824 * @param pvUser1 Null, not used.
9825 * @param pvUser2 Null, not used.
9826 */
9827static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9828{
9829 RT_NOREF3(idCpu, pvUser1, pvUser2);
9830 VMXDispatchHostNmi();
9831}
9832
9833
9834/**
9835 * Dispatching an NMI on the host CPU that received it.
9836 *
9837 * @returns VBox status code.
9838 * @param pVCpu The cross context virtual CPU structure.
9839 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9840 * executing when receiving the host NMI in VMX non-root
9841 * operation.
9842 */
9843static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9844{
9845 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
9846 Assert(idCpu != NIL_RTCPUID);
9847
9848 /*
9849 * We don't want to delay dispatching the NMI any more than we have to. However,
9850 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9851 * after executing guest or nested-guest code for the following reasons:
9852 *
9853 * - We would need to perform VMREADs with interrupts disabled and is orders of
9854 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
9855 * supported by the host hypervisor.
9856 *
9857 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9858 * longer period of time just for handling an edge case like host NMIs which do
9859 * not occur nearly as frequently as other VM-exits.
9860 *
9861 * Let's cover the most likely scenario first. Check if we are on the target CPU
9862 * and dispatch the NMI right away. This should be much faster than calling into
9863 * RTMpOnSpecific() machinery.
9864 */
9865 bool fDispatched = false;
9866 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9867 if (idCpu == RTMpCpuId())
9868 {
9869 VMXDispatchHostNmi();
9870 fDispatched = true;
9871 }
9872 ASMSetFlags(fEFlags);
9873 if (fDispatched)
9874 {
9875 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9876 return VINF_SUCCESS;
9877 }
9878
9879 /*
9880 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9881 * there should be no race or recursion even if we are unlucky enough to be preempted
9882 * (to the target CPU) without dispatching the host NMI above.
9883 */
9884 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9885 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9886}
9887
9888
9889#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9890/**
9891 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9892 * nested-guest using hardware-assisted VMX.
9893 *
9894 * @param pVCpu The cross context virtual CPU structure.
9895 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9896 * @param pVmcsInfoGst The guest VMCS info. object.
9897 */
9898static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9899{
9900 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9901 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9902 Assert(pu64MsrBitmap);
9903
9904 /*
9905 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9906 * MSR that is intercepted by the guest is also intercepted while executing the
9907 * nested-guest using hardware-assisted VMX.
9908 *
9909 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9910 * nested-guest VM-exit even if the outer guest is not intercepting some
9911 * MSRs. We cannot assume the caller has initialized the nested-guest
9912 * MSR bitmap in this case.
9913 *
9914 * The guest hypervisor may also switch whether it uses MSR bitmaps for
9915 * each VM-entry, hence initializing it once per-VM while setting up the
9916 * nested-guest VMCS is not sufficient.
9917 */
9918 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9919 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9920 {
9921 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9922 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9923 Assert(pu64MsrBitmapNstGst);
9924 Assert(pu64MsrBitmapGst);
9925
9926 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9927 for (uint32_t i = 0; i < cFrags; i++)
9928 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9929 }
9930 else
9931 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9932}
9933
9934
9935/**
9936 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9937 * hardware-assisted VMX execution of the nested-guest.
9938 *
9939 * For a guest, we don't modify these controls once we set up the VMCS and hence
9940 * this function is never called.
9941 *
9942 * For nested-guests since the guest hypervisor provides these controls on every
9943 * nested-guest VM-entry and could potentially change them everytime we need to
9944 * merge them before every nested-guest VM-entry.
9945 *
9946 * @returns VBox status code.
9947 * @param pVCpu The cross context virtual CPU structure.
9948 */
9949static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9950{
9951 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9952 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9953 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9954 Assert(pVmcsNstGst);
9955
9956 /*
9957 * Merge the controls with the requirements of the guest VMCS.
9958 *
9959 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9960 * VMCS with the features supported by the physical CPU as it's already done by the
9961 * VMLAUNCH/VMRESUME instruction emulation.
9962 *
9963 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9964 * derived from the VMX features supported by the physical CPU.
9965 */
9966
9967 /* Pin-based VM-execution controls. */
9968 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9969
9970 /* Processor-based VM-execution controls. */
9971 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9972 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9973 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9974 | VMX_PROC_CTLS_USE_TPR_SHADOW
9975 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9976
9977 /* Secondary processor-based VM-execution controls. */
9978 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9979 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9980 | VMX_PROC_CTLS2_INVPCID
9981 | VMX_PROC_CTLS2_VMCS_SHADOWING
9982 | VMX_PROC_CTLS2_RDTSCP
9983 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9984 | VMX_PROC_CTLS2_APIC_REG_VIRT
9985 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9986 | VMX_PROC_CTLS2_VMFUNC));
9987
9988 /*
9989 * VM-entry controls:
9990 * These controls contains state that depends on the nested-guest state (primarily
9991 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
9992 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
9993 * properly continue executing the nested-guest if the EFER MSR changes but does not
9994 * cause a nested-guest VM-exits.
9995 *
9996 * VM-exit controls:
9997 * These controls specify the host state on return. We cannot use the controls from
9998 * the guest hypervisor state as is as it would contain the guest state rather than
9999 * the host state. Since the host state is subject to change (e.g. preemption, trips
10000 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10001 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10002 *
10003 * VM-entry MSR-load:
10004 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10005 * context by the VMLAUNCH/VMRESUME instruction emulation.
10006 *
10007 * VM-exit MSR-store:
10008 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10009 * back into the VM-exit MSR-store area.
10010 *
10011 * VM-exit MSR-load areas:
10012 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10013 * can entirely ignore what the guest hypervisor wants to load here.
10014 */
10015
10016 /*
10017 * Exception bitmap.
10018 *
10019 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10020 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10021 * code more flexible if intercepting exceptions become more dynamic in the future we do
10022 * it as part of exporting the nested-guest state.
10023 */
10024 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10025
10026 /*
10027 * CR0/CR4 guest/host mask.
10028 *
10029 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10030 * cause VM-exits, so we need to merge them here.
10031 */
10032 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10033 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10034
10035 /*
10036 * Page-fault error-code mask and match.
10037 *
10038 * Although we require unrestricted guest execution (and thereby nested-paging) for
10039 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10040 * normally intercept #PFs, it might intercept them for debugging purposes.
10041 *
10042 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10043 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10044 */
10045 uint32_t u32XcptPFMask;
10046 uint32_t u32XcptPFMatch;
10047 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10048 {
10049 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10050 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10051 }
10052 else
10053 {
10054 u32XcptPFMask = 0;
10055 u32XcptPFMatch = 0;
10056 }
10057
10058 /*
10059 * Pause-Loop exiting.
10060 */
10061 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10062 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10063
10064 /*
10065 * Pending debug exceptions.
10066 * Currently just copy whatever the nested-guest provides us.
10067 */
10068 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10069
10070 /*
10071 * I/O Bitmap.
10072 *
10073 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10074 * intercept all I/O port accesses.
10075 */
10076 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10077 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10078
10079 /*
10080 * VMCS shadowing.
10081 *
10082 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10083 * enabled while executing the nested-guest.
10084 */
10085 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10086
10087 /*
10088 * APIC-access page.
10089 */
10090 RTHCPHYS HCPhysApicAccess;
10091 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10092 {
10093 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10094 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10095
10096 /** @todo NSTVMX: This is not really correct but currently is required to make
10097 * things work. We need to re-enable the page handler when we fallback to
10098 * IEM execution of the nested-guest! */
10099 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10100
10101 void *pvPage;
10102 PGMPAGEMAPLOCK PgLockApicAccess;
10103 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10104 if (RT_SUCCESS(rc))
10105 {
10106 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10107 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10108
10109 /** @todo Handle proper releasing of page-mapping lock later. */
10110 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10111 }
10112 else
10113 return rc;
10114 }
10115 else
10116 HCPhysApicAccess = 0;
10117
10118 /*
10119 * Virtual-APIC page and TPR threshold.
10120 */
10121 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10122 RTHCPHYS HCPhysVirtApic;
10123 uint32_t u32TprThreshold;
10124 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10125 {
10126 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10127 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10128
10129 void *pvPage;
10130 PGMPAGEMAPLOCK PgLockVirtApic;
10131 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10132 if (RT_SUCCESS(rc))
10133 {
10134 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10135 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10136
10137 /** @todo Handle proper releasing of page-mapping lock later. */
10138 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10139 }
10140 else
10141 return rc;
10142
10143 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10144 }
10145 else
10146 {
10147 HCPhysVirtApic = 0;
10148 u32TprThreshold = 0;
10149
10150 /*
10151 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10152 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10153 * be taken care of by EPT/shadow paging.
10154 */
10155 if (pVM->hm.s.fAllow64BitGuests)
10156 {
10157 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10158 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10159 }
10160 }
10161
10162 /*
10163 * Validate basic assumptions.
10164 */
10165 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10166 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10167 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10168
10169 /*
10170 * Commit it to the nested-guest VMCS.
10171 */
10172 int rc = VINF_SUCCESS;
10173 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10174 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10175 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10176 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10177 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10178 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10179 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10180 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10181 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10182 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10183 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10184 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10185 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10186 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10187 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10188 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10189 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10190 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10191 {
10192 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10193 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10194 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10195 }
10196 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10197 {
10198 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10199 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10200 }
10201 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10202 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10203 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10204 AssertRC(rc);
10205
10206 /*
10207 * Update the nested-guest VMCS cache.
10208 */
10209 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10210 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10211 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10212 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10213 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10214 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10215 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10216 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10217 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10218
10219 /*
10220 * We need to flush the TLB if we are switching the APIC-access page address.
10221 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10222 */
10223 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10224 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10225
10226 /*
10227 * MSR bitmap.
10228 *
10229 * The MSR bitmap address has already been initialized while setting up the nested-guest
10230 * VMCS, here we need to merge the MSR bitmaps.
10231 */
10232 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10233 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10234
10235 return VINF_SUCCESS;
10236}
10237#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10238
10239
10240/**
10241 * Does the preparations before executing guest code in VT-x.
10242 *
10243 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10244 * recompiler/IEM. We must be cautious what we do here regarding committing
10245 * guest-state information into the VMCS assuming we assuredly execute the
10246 * guest in VT-x mode.
10247 *
10248 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10249 * the common-state (TRPM/forceflags), we must undo those changes so that the
10250 * recompiler/IEM can (and should) use them when it resumes guest execution.
10251 * Otherwise such operations must be done when we can no longer exit to ring-3.
10252 *
10253 * @returns Strict VBox status code (i.e. informational status codes too).
10254 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10255 * have been disabled.
10256 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10257 * pending events).
10258 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10259 * double-fault into the guest.
10260 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10261 * dispatched directly.
10262 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10263 *
10264 * @param pVCpu The cross context virtual CPU structure.
10265 * @param pVmxTransient The VMX-transient structure.
10266 * @param fStepping Whether we are single-stepping the guest in the
10267 * hypervisor debugger. Makes us ignore some of the reasons
10268 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10269 * if event dispatching took place.
10270 */
10271static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10272{
10273 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10274
10275 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10276
10277#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10278 if (pVmxTransient->fIsNestedGuest)
10279 {
10280 RT_NOREF2(pVCpu, fStepping);
10281 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10282 return VINF_EM_RESCHEDULE_REM;
10283 }
10284#endif
10285
10286#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10287 PGMRZDynMapFlushAutoSet(pVCpu);
10288#endif
10289
10290 /*
10291 * Check and process force flag actions, some of which might require us to go back to ring-3.
10292 */
10293 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10294 if (rcStrict == VINF_SUCCESS)
10295 {
10296 /* FFs don't get set all the time. */
10297#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10298 if ( pVmxTransient->fIsNestedGuest
10299 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10300 {
10301 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10302 return VINF_VMX_VMEXIT;
10303 }
10304#endif
10305 }
10306 else
10307 return rcStrict;
10308
10309 /*
10310 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10311 */
10312 /** @todo Doing this from ring-3 after VM setup phase causes a
10313 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10314 * idea why atm. */
10315 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10316 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10317 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10318 && PDMHasApic(pVM))
10319 {
10320 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10321 AssertRCReturn(rc, rc);
10322 }
10323
10324#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10325 /*
10326 * Merge guest VMCS controls with the nested-guest VMCS controls.
10327 *
10328 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10329 * saved state), we should be okay with merging controls as we initialize the
10330 * guest VMCS controls as part of VM setup phase.
10331 */
10332 if ( pVmxTransient->fIsNestedGuest
10333 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10334 {
10335 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10336 AssertRCReturn(rc, rc);
10337 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10338 }
10339#endif
10340
10341 /*
10342 * Evaluate events to be injected into the guest.
10343 *
10344 * Events in TRPM can be injected without inspecting the guest state.
10345 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10346 * guest to cause a VM-exit the next time they are ready to receive the event.
10347 *
10348 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10349 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10350 * subject to interecption. Otherwise, we should have checked and injected them
10351 * manually elsewhere (IEM).
10352 */
10353 if (TRPMHasTrap(pVCpu))
10354 {
10355 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10356 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10357 }
10358
10359 uint32_t fIntrState;
10360 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10361
10362#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10363 /*
10364 * While evaluating pending events if something failed (unlikely) or if we were
10365 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10366 */
10367 if (rcStrict != VINF_SUCCESS)
10368 return rcStrict;
10369 if ( pVmxTransient->fIsNestedGuest
10370 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10371 {
10372 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10373 return VINF_VMX_VMEXIT;
10374 }
10375#else
10376 Assert(rcStrict == VINF_SUCCESS);
10377#endif
10378
10379 /*
10380 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10381 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10382 * also result in triple-faulting the VM.
10383 *
10384 * With nested-guests, the above does not apply since unrestricted guest execution is a
10385 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10386 */
10387 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10388 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10389 { /* likely */ }
10390 else
10391 {
10392 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10393 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10394 return rcStrict;
10395 }
10396
10397 /*
10398 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10399 * import CR3 themselves. We will need to update them here, as even as late as the above
10400 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10401 * the below force flags to be set.
10402 */
10403 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10404 {
10405 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10406 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10407 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10408 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10409 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10410 }
10411 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10412 {
10413 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10414 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10415 }
10416
10417#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10418 /* Paranoia. */
10419 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10420#endif
10421
10422 /*
10423 * No longjmps to ring-3 from this point on!!!
10424 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10425 * This also disables flushing of the R0-logger instance (if any).
10426 */
10427 VMMRZCallRing3Disable(pVCpu);
10428
10429 /*
10430 * Export the guest state bits.
10431 *
10432 * We cannot perform longjmps while loading the guest state because we do not preserve the
10433 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10434 * CPU migration.
10435 *
10436 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10437 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10438 */
10439 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10440 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10441 { /* likely */ }
10442 else
10443 {
10444 VMMRZCallRing3Enable(pVCpu);
10445 return rcStrict;
10446 }
10447
10448 /*
10449 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10450 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10451 * preemption disabled for a while. Since this is purely to aid the
10452 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10453 * disable interrupt on NT.
10454 *
10455 * We need to check for force-flags that could've possible been altered since we last
10456 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10457 * see @bugref{6398}).
10458 *
10459 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10460 * to ring-3 before executing guest code.
10461 */
10462 pVmxTransient->fEFlags = ASMIntDisableFlags();
10463
10464 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10465 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10466 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10467 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10468 {
10469 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10470 {
10471#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10472 /*
10473 * If we are executing a nested-guest make sure that we should intercept subsequent
10474 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10475 * the VM-exit instruction emulation happy.
10476 */
10477 if (pVmxTransient->fIsNestedGuest)
10478 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10479#endif
10480
10481 /*
10482 * We've injected any pending events. This is really the point of no return (to ring-3).
10483 *
10484 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10485 * returns from this function, so do -not- enable them here.
10486 */
10487 pVCpu->hm.s.Event.fPending = false;
10488 return VINF_SUCCESS;
10489 }
10490
10491 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10492 rcStrict = VINF_EM_RAW_INTERRUPT;
10493 }
10494 else
10495 {
10496 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10497 rcStrict = VINF_EM_RAW_TO_R3;
10498 }
10499
10500 ASMSetFlags(pVmxTransient->fEFlags);
10501 VMMRZCallRing3Enable(pVCpu);
10502
10503 return rcStrict;
10504}
10505
10506
10507/**
10508 * Final preparations before executing guest code using hardware-assisted VMX.
10509 *
10510 * We can no longer get preempted to a different host CPU and there are no returns
10511 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10512 * failures), this function is not intended to fail sans unrecoverable hardware
10513 * errors.
10514 *
10515 * @param pVCpu The cross context virtual CPU structure.
10516 * @param pVmxTransient The VMX-transient structure.
10517 *
10518 * @remarks Called with preemption disabled.
10519 * @remarks No-long-jump zone!!!
10520 */
10521static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10522{
10523 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10524 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10525 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10526 Assert(!pVCpu->hm.s.Event.fPending);
10527
10528 /*
10529 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10530 */
10531 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10532 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10533
10534 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10535 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10536 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10537 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10538
10539 if (!CPUMIsGuestFPUStateActive(pVCpu))
10540 {
10541 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10542 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10543 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10544 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10545 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10546 }
10547
10548 /*
10549 * Re-export the host state bits as we may've been preempted (only happens when
10550 * thread-context hooks are used or when the VM start function changes) or if
10551 * the host CR0 is modified while loading the guest FPU state above.
10552 *
10553 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10554 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10555 * see @bugref{8432}.
10556 *
10557 * This may also happen when switching to/from a nested-guest VMCS without leaving
10558 * ring-0.
10559 */
10560 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10561 {
10562 hmR0VmxExportHostState(pVCpu);
10563 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10564 }
10565 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10566
10567 /*
10568 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10569 */
10570 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10571 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10572 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10573
10574 /*
10575 * Store status of the shared guest/host debug state at the time of VM-entry.
10576 */
10577 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10578 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10579
10580 /*
10581 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10582 * more than one conditional check. The post-run side of our code shall determine
10583 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10584 */
10585 if (pVmcsInfo->pbVirtApic)
10586 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10587
10588 /*
10589 * Update the host MSRs values in the VM-exit MSR-load area.
10590 */
10591 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10592 {
10593 if (pVmcsInfo->cExitMsrLoad > 0)
10594 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10595 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10596 }
10597
10598 /*
10599 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10600 * VMX-preemption timer based on the next virtual sync clock deadline.
10601 */
10602 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10603 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10604 {
10605 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10606 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10607 }
10608
10609 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10610 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10611 if (!fIsRdtscIntercepted)
10612 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10613 else
10614 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10615
10616 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10617 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10618 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10619 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10620 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10621 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10622
10623 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10624
10625 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10626 as we're about to start executing the guest. */
10627
10628 /*
10629 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10630 *
10631 * This is done this late as updating the TSC offsetting/preemption timer above
10632 * figures out if we can skip intercepting RDTSCP by calculating the number of
10633 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10634 */
10635 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10636 && !fIsRdtscIntercepted)
10637 {
10638 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10639
10640 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10641 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10642 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10643 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10644 AssertRC(rc);
10645 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10646 pVmxTransient->fRemoveTscAuxMsr = true;
10647 }
10648
10649#ifdef VBOX_STRICT
10650 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10651 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10652 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10653 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10654#endif
10655
10656#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10657 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10658 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10659 * see @bugref{9180#c54}. */
10660 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10661 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10662 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10663#endif
10664}
10665
10666
10667/**
10668 * First C routine invoked after running guest code using hardware-assisted VMX.
10669 *
10670 * @param pVCpu The cross context virtual CPU structure.
10671 * @param pVmxTransient The VMX-transient structure.
10672 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10673 *
10674 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10675 *
10676 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10677 * unconditionally when it is safe to do so.
10678 */
10679static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10680{
10681 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10682
10683 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10684 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10685 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10686 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10687 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10688 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10689
10690 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10691 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10692 {
10693 uint64_t uGstTsc;
10694 if (!pVmxTransient->fIsNestedGuest)
10695 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10696 else
10697 {
10698 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10699 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10700 }
10701 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10702 }
10703
10704 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10705 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10706 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10707
10708 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10709 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10710#ifdef VBOX_STRICT
10711 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10712#endif
10713 Assert(!ASMIntAreEnabled());
10714 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10715 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10716
10717#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10718 /*
10719 * Clean all the VMCS fields in the transient structure before reading
10720 * anything from the VMCS.
10721 */
10722 pVmxTransient->uExitReason = 0;
10723 pVmxTransient->uExitIntErrorCode = 0;
10724 pVmxTransient->uExitQual = 0;
10725 pVmxTransient->uGuestLinearAddr = 0;
10726 pVmxTransient->uExitIntInfo = 0;
10727 pVmxTransient->cbExitInstr = 0;
10728 pVmxTransient->ExitInstrInfo.u = 0;
10729 pVmxTransient->uEntryIntInfo = 0;
10730 pVmxTransient->uEntryXcptErrorCode = 0;
10731 pVmxTransient->cbEntryInstr = 0;
10732 pVmxTransient->uIdtVectoringInfo = 0;
10733 pVmxTransient->uIdtVectoringErrorCode = 0;
10734#endif
10735
10736 /*
10737 * Save the basic VM-exit reason and check if the VM-entry failed.
10738 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10739 */
10740 uint32_t uExitReason;
10741 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10742 AssertRC(rc);
10743 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10744 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10745
10746 /*
10747 * Log the VM-exit before logging anything else as otherwise it might be a
10748 * tad confusing what happens before and after the world-switch.
10749 */
10750 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10751
10752 /*
10753 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10754 * bitmap permissions, if it was added before VM-entry.
10755 */
10756 if (pVmxTransient->fRemoveTscAuxMsr)
10757 {
10758 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10759 pVmxTransient->fRemoveTscAuxMsr = false;
10760 }
10761
10762 /*
10763 * Check if VMLAUNCH/VMRESUME succeeded.
10764 * If this failed, we cause a guru meditation and cease further execution.
10765 *
10766 * However, if we are executing a nested-guest we might fail if we use the
10767 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10768 */
10769 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10770 {
10771 /*
10772 * Update the VM-exit history array here even if the VM-entry failed due to:
10773 * - Invalid guest state.
10774 * - MSR loading.
10775 * - Machine-check event.
10776 *
10777 * In any of the above cases we will still have a "valid" VM-exit reason
10778 * despite @a fVMEntryFailed being false.
10779 *
10780 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10781 *
10782 * Note! We don't have CS or RIP at this point. Will probably address that later
10783 * by amending the history entry added here.
10784 */
10785 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10786 UINT64_MAX, uHostTsc);
10787
10788 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10789 {
10790 VMMRZCallRing3Enable(pVCpu);
10791
10792 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10793 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10794
10795#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10796 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10797#endif
10798#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10799 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10800 AssertRC(rc);
10801#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10802 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10803 AssertRC(rc);
10804#else
10805 /*
10806 * Import the guest-interruptibility state always as we need it while evaluating
10807 * injecting events on re-entry.
10808 *
10809 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10810 * checking for real-mode while exporting the state because all bits that cause
10811 * mode changes wrt CR0 are intercepted.
10812 */
10813 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10814 AssertRC(rc);
10815#endif
10816
10817 /*
10818 * Sync the TPR shadow with our APIC state.
10819 */
10820 if ( !pVmxTransient->fIsNestedGuest
10821 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10822 {
10823 Assert(pVmcsInfo->pbVirtApic);
10824 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10825 {
10826 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10827 AssertRC(rc);
10828 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10829 }
10830 }
10831
10832 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10833 return;
10834 }
10835 }
10836#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10837 else if (pVmxTransient->fIsNestedGuest)
10838 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10839#endif
10840 else
10841 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10842
10843 VMMRZCallRing3Enable(pVCpu);
10844}
10845
10846
10847/**
10848 * Runs the guest code using hardware-assisted VMX the normal way.
10849 *
10850 * @returns VBox status code.
10851 * @param pVCpu The cross context virtual CPU structure.
10852 * @param pcLoops Pointer to the number of executed loops.
10853 */
10854static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10855{
10856 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10857 Assert(pcLoops);
10858 Assert(*pcLoops <= cMaxResumeLoops);
10859 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10860
10861#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10862 /*
10863 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10864 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10865 * guest VMCS while entering the VMX ring-0 session.
10866 */
10867 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10868 {
10869 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10870 if (RT_SUCCESS(rc))
10871 { /* likely */ }
10872 else
10873 {
10874 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10875 return rc;
10876 }
10877 }
10878#endif
10879
10880 VMXTRANSIENT VmxTransient;
10881 RT_ZERO(VmxTransient);
10882 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10883
10884 /* Paranoia. */
10885 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10886
10887 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10888 for (;;)
10889 {
10890 Assert(!HMR0SuspendPending());
10891 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10892 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10893
10894 /*
10895 * Preparatory work for running nested-guest code, this may force us to
10896 * return to ring-3.
10897 *
10898 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10899 */
10900 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10901 if (rcStrict != VINF_SUCCESS)
10902 break;
10903
10904 /* Interrupts are disabled at this point! */
10905 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10906 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10907 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10908 /* Interrupts are re-enabled at this point! */
10909
10910 /*
10911 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10912 */
10913 if (RT_SUCCESS(rcRun))
10914 { /* very likely */ }
10915 else
10916 {
10917 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10918 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10919 return rcRun;
10920 }
10921
10922 /*
10923 * Profile the VM-exit.
10924 */
10925 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10926 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10927 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10928 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10929 HMVMX_START_EXIT_DISPATCH_PROF();
10930
10931 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10932
10933 /*
10934 * Handle the VM-exit.
10935 */
10936#ifdef HMVMX_USE_FUNCTION_TABLE
10937 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10938#else
10939 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10940#endif
10941 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10942 if (rcStrict == VINF_SUCCESS)
10943 {
10944 if (++(*pcLoops) <= cMaxResumeLoops)
10945 continue;
10946 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10947 rcStrict = VINF_EM_RAW_INTERRUPT;
10948 }
10949 break;
10950 }
10951
10952 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10953 return rcStrict;
10954}
10955
10956
10957#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10958/**
10959 * Runs the nested-guest code using hardware-assisted VMX.
10960 *
10961 * @returns VBox status code.
10962 * @param pVCpu The cross context virtual CPU structure.
10963 * @param pcLoops Pointer to the number of executed loops.
10964 *
10965 * @sa hmR0VmxRunGuestCodeNormal.
10966 */
10967static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10968{
10969 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10970 Assert(pcLoops);
10971 Assert(*pcLoops <= cMaxResumeLoops);
10972 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10973
10974 /*
10975 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10976 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10977 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10978 */
10979 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10980 {
10981 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10982 if (RT_SUCCESS(rc))
10983 { /* likely */ }
10984 else
10985 {
10986 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
10987 return rc;
10988 }
10989 }
10990
10991 VMXTRANSIENT VmxTransient;
10992 RT_ZERO(VmxTransient);
10993 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10994 VmxTransient.fIsNestedGuest = true;
10995
10996 /* Paranoia. */
10997 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10998
10999 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11000 for (;;)
11001 {
11002 Assert(!HMR0SuspendPending());
11003 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11004 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11005
11006 /*
11007 * Preparatory work for running guest code, this may force us to
11008 * return to ring-3.
11009 *
11010 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11011 */
11012 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11013 if (rcStrict != VINF_SUCCESS)
11014 break;
11015
11016 /* Interrupts are disabled at this point! */
11017 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11018 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11019 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11020 /* Interrupts are re-enabled at this point! */
11021
11022 /*
11023 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11024 */
11025 if (RT_SUCCESS(rcRun))
11026 { /* very likely */ }
11027 else
11028 {
11029 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11030 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11031 return rcRun;
11032 }
11033
11034 /*
11035 * Profile the VM-exit.
11036 */
11037 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11038 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11039 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11040 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11041 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11042 HMVMX_START_EXIT_DISPATCH_PROF();
11043
11044 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11045
11046 /*
11047 * Handle the VM-exit.
11048 */
11049 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11050 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11051 if (rcStrict == VINF_SUCCESS)
11052 {
11053 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11054 {
11055 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11056 rcStrict = VINF_VMX_VMEXIT;
11057 }
11058 else
11059 {
11060 if (++(*pcLoops) <= cMaxResumeLoops)
11061 continue;
11062 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11063 rcStrict = VINF_EM_RAW_INTERRUPT;
11064 }
11065 }
11066 else
11067 Assert(rcStrict != VINF_VMX_VMEXIT);
11068 break;
11069 }
11070
11071 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11072 return rcStrict;
11073}
11074#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11075
11076
11077/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11078 * probes.
11079 *
11080 * The following few functions and associated structure contains the bloat
11081 * necessary for providing detailed debug events and dtrace probes as well as
11082 * reliable host side single stepping. This works on the principle of
11083 * "subclassing" the normal execution loop and workers. We replace the loop
11084 * method completely and override selected helpers to add necessary adjustments
11085 * to their core operation.
11086 *
11087 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11088 * any performance for debug and analysis features.
11089 *
11090 * @{
11091 */
11092
11093/**
11094 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11095 * the debug run loop.
11096 */
11097typedef struct VMXRUNDBGSTATE
11098{
11099 /** The RIP we started executing at. This is for detecting that we stepped. */
11100 uint64_t uRipStart;
11101 /** The CS we started executing with. */
11102 uint16_t uCsStart;
11103
11104 /** Whether we've actually modified the 1st execution control field. */
11105 bool fModifiedProcCtls : 1;
11106 /** Whether we've actually modified the 2nd execution control field. */
11107 bool fModifiedProcCtls2 : 1;
11108 /** Whether we've actually modified the exception bitmap. */
11109 bool fModifiedXcptBitmap : 1;
11110
11111 /** We desire the modified the CR0 mask to be cleared. */
11112 bool fClearCr0Mask : 1;
11113 /** We desire the modified the CR4 mask to be cleared. */
11114 bool fClearCr4Mask : 1;
11115 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11116 uint32_t fCpe1Extra;
11117 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11118 uint32_t fCpe1Unwanted;
11119 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11120 uint32_t fCpe2Extra;
11121 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11122 uint32_t bmXcptExtra;
11123 /** The sequence number of the Dtrace provider settings the state was
11124 * configured against. */
11125 uint32_t uDtraceSettingsSeqNo;
11126 /** VM-exits to check (one bit per VM-exit). */
11127 uint32_t bmExitsToCheck[3];
11128
11129 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11130 uint32_t fProcCtlsInitial;
11131 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11132 uint32_t fProcCtls2Initial;
11133 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11134 uint32_t bmXcptInitial;
11135} VMXRUNDBGSTATE;
11136AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11137typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11138
11139
11140/**
11141 * Initializes the VMXRUNDBGSTATE structure.
11142 *
11143 * @param pVCpu The cross context virtual CPU structure of the
11144 * calling EMT.
11145 * @param pVmxTransient The VMX-transient structure.
11146 * @param pDbgState The debug state to initialize.
11147 */
11148static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11149{
11150 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11151 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11152
11153 pDbgState->fModifiedProcCtls = false;
11154 pDbgState->fModifiedProcCtls2 = false;
11155 pDbgState->fModifiedXcptBitmap = false;
11156 pDbgState->fClearCr0Mask = false;
11157 pDbgState->fClearCr4Mask = false;
11158 pDbgState->fCpe1Extra = 0;
11159 pDbgState->fCpe1Unwanted = 0;
11160 pDbgState->fCpe2Extra = 0;
11161 pDbgState->bmXcptExtra = 0;
11162 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11163 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11164 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11165}
11166
11167
11168/**
11169 * Updates the VMSC fields with changes requested by @a pDbgState.
11170 *
11171 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11172 * immediately before executing guest code, i.e. when interrupts are disabled.
11173 * We don't check status codes here as we cannot easily assert or return in the
11174 * latter case.
11175 *
11176 * @param pVCpu The cross context virtual CPU structure.
11177 * @param pVmxTransient The VMX-transient structure.
11178 * @param pDbgState The debug state.
11179 */
11180static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11181{
11182 /*
11183 * Ensure desired flags in VMCS control fields are set.
11184 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11185 *
11186 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11187 * there should be no stale data in pCtx at this point.
11188 */
11189 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11190 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11191 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11192 {
11193 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11194 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11195 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11196 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11197 pDbgState->fModifiedProcCtls = true;
11198 }
11199
11200 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11201 {
11202 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11203 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11204 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11205 pDbgState->fModifiedProcCtls2 = true;
11206 }
11207
11208 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11209 {
11210 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11211 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11212 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11213 pDbgState->fModifiedXcptBitmap = true;
11214 }
11215
11216 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11217 {
11218 pVmcsInfo->u64Cr0Mask = 0;
11219 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11220 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11221 }
11222
11223 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11224 {
11225 pVmcsInfo->u64Cr4Mask = 0;
11226 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11227 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11228 }
11229
11230 NOREF(pVCpu);
11231}
11232
11233
11234/**
11235 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11236 * re-entry next time around.
11237 *
11238 * @returns Strict VBox status code (i.e. informational status codes too).
11239 * @param pVCpu The cross context virtual CPU structure.
11240 * @param pVmxTransient The VMX-transient structure.
11241 * @param pDbgState The debug state.
11242 * @param rcStrict The return code from executing the guest using single
11243 * stepping.
11244 */
11245static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11246 VBOXSTRICTRC rcStrict)
11247{
11248 /*
11249 * Restore VM-exit control settings as we may not reenter this function the
11250 * next time around.
11251 */
11252 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11253
11254 /* We reload the initial value, trigger what we can of recalculations the
11255 next time around. From the looks of things, that's all that's required atm. */
11256 if (pDbgState->fModifiedProcCtls)
11257 {
11258 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11259 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11260 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11261 AssertRC(rc2);
11262 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11263 }
11264
11265 /* We're currently the only ones messing with this one, so just restore the
11266 cached value and reload the field. */
11267 if ( pDbgState->fModifiedProcCtls2
11268 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11269 {
11270 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11271 AssertRC(rc2);
11272 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11273 }
11274
11275 /* If we've modified the exception bitmap, we restore it and trigger
11276 reloading and partial recalculation the next time around. */
11277 if (pDbgState->fModifiedXcptBitmap)
11278 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11279
11280 return rcStrict;
11281}
11282
11283
11284/**
11285 * Configures VM-exit controls for current DBGF and DTrace settings.
11286 *
11287 * This updates @a pDbgState and the VMCS execution control fields to reflect
11288 * the necessary VM-exits demanded by DBGF and DTrace.
11289 *
11290 * @param pVCpu The cross context virtual CPU structure.
11291 * @param pVmxTransient The VMX-transient structure. May update
11292 * fUpdatedTscOffsettingAndPreemptTimer.
11293 * @param pDbgState The debug state.
11294 */
11295static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11296{
11297 /*
11298 * Take down the dtrace serial number so we can spot changes.
11299 */
11300 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11301 ASMCompilerBarrier();
11302
11303 /*
11304 * We'll rebuild most of the middle block of data members (holding the
11305 * current settings) as we go along here, so start by clearing it all.
11306 */
11307 pDbgState->bmXcptExtra = 0;
11308 pDbgState->fCpe1Extra = 0;
11309 pDbgState->fCpe1Unwanted = 0;
11310 pDbgState->fCpe2Extra = 0;
11311 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11312 pDbgState->bmExitsToCheck[i] = 0;
11313
11314 /*
11315 * Software interrupts (INT XXh) - no idea how to trigger these...
11316 */
11317 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11318 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11319 || VBOXVMM_INT_SOFTWARE_ENABLED())
11320 {
11321 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11322 }
11323
11324 /*
11325 * INT3 breakpoints - triggered by #BP exceptions.
11326 */
11327 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11328 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11329
11330 /*
11331 * Exception bitmap and XCPT events+probes.
11332 */
11333 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11334 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11335 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11336
11337 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11338 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11339 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11340 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11341 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11342 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11343 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11344 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11345 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11346 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11347 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11348 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11349 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11350 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11351 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11352 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11353 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11354 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11355
11356 if (pDbgState->bmXcptExtra)
11357 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11358
11359 /*
11360 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11361 *
11362 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11363 * So, when adding/changing/removing please don't forget to update it.
11364 *
11365 * Some of the macros are picking up local variables to save horizontal space,
11366 * (being able to see it in a table is the lesser evil here).
11367 */
11368#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11369 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11370 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11371#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11372 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11373 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11374 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11375 } else do { } while (0)
11376#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11377 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11378 { \
11379 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11380 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11381 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11382 } else do { } while (0)
11383#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11384 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11385 { \
11386 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11387 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11388 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11389 } else do { } while (0)
11390#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11391 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11392 { \
11393 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11394 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11395 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11396 } else do { } while (0)
11397
11398 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11399 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11400 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11401 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11402 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11403
11404 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11405 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11406 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11407 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11408 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11409 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11410 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11411 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11412 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11413 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11414 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11415 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11416 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11417 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11418 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11419 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11420 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11421 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11422 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11423 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11424 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11425 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11426 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11427 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11428 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11429 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11430 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11431 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11432 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11433 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11434 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11435 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11436 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11437 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11438 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11439 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11440
11441 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11442 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11443 {
11444 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11445 | CPUMCTX_EXTRN_APIC_TPR);
11446 AssertRC(rc);
11447
11448#if 0 /** @todo fix me */
11449 pDbgState->fClearCr0Mask = true;
11450 pDbgState->fClearCr4Mask = true;
11451#endif
11452 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11453 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11454 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11455 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11456 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11457 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11458 require clearing here and in the loop if we start using it. */
11459 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11460 }
11461 else
11462 {
11463 if (pDbgState->fClearCr0Mask)
11464 {
11465 pDbgState->fClearCr0Mask = false;
11466 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11467 }
11468 if (pDbgState->fClearCr4Mask)
11469 {
11470 pDbgState->fClearCr4Mask = false;
11471 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11472 }
11473 }
11474 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11475 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11476
11477 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11478 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11479 {
11480 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11481 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11482 }
11483 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11484 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11485
11486 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11487 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11488 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11489 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11490 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11491 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11492 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11493 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11494#if 0 /** @todo too slow, fix handler. */
11495 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11496#endif
11497 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11498
11499 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11500 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11501 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11502 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11503 {
11504 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11505 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11506 }
11507 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11508 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11509 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11510 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11511
11512 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11513 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11514 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11515 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11516 {
11517 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11518 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11519 }
11520 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11521 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11522 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11523 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11524
11525 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11526 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11527 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11528 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11529 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11530 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11531 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11532 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11533 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11534 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11535 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11536 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11537 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11538 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11539 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11540 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11541 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11542 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11543 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11544 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11545 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11546 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11547
11548#undef IS_EITHER_ENABLED
11549#undef SET_ONLY_XBM_IF_EITHER_EN
11550#undef SET_CPE1_XBM_IF_EITHER_EN
11551#undef SET_CPEU_XBM_IF_EITHER_EN
11552#undef SET_CPE2_XBM_IF_EITHER_EN
11553
11554 /*
11555 * Sanitize the control stuff.
11556 */
11557 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11558 if (pDbgState->fCpe2Extra)
11559 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11560 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11561 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11562 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11563 {
11564 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11565 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11566 }
11567
11568 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11569 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11570 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11571 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11572}
11573
11574
11575/**
11576 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11577 * appropriate.
11578 *
11579 * The caller has checked the VM-exit against the
11580 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11581 * already, so we don't have to do that either.
11582 *
11583 * @returns Strict VBox status code (i.e. informational status codes too).
11584 * @param pVCpu The cross context virtual CPU structure.
11585 * @param pVmxTransient The VMX-transient structure.
11586 * @param uExitReason The VM-exit reason.
11587 *
11588 * @remarks The name of this function is displayed by dtrace, so keep it short
11589 * and to the point. No longer than 33 chars long, please.
11590 */
11591static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11592{
11593 /*
11594 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11595 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11596 *
11597 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11598 * does. Must add/change/remove both places. Same ordering, please.
11599 *
11600 * Added/removed events must also be reflected in the next section
11601 * where we dispatch dtrace events.
11602 */
11603 bool fDtrace1 = false;
11604 bool fDtrace2 = false;
11605 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11606 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11607 uint32_t uEventArg = 0;
11608#define SET_EXIT(a_EventSubName) \
11609 do { \
11610 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11611 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11612 } while (0)
11613#define SET_BOTH(a_EventSubName) \
11614 do { \
11615 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11616 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11617 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11618 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11619 } while (0)
11620 switch (uExitReason)
11621 {
11622 case VMX_EXIT_MTF:
11623 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11624
11625 case VMX_EXIT_XCPT_OR_NMI:
11626 {
11627 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11628 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11629 {
11630 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11631 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11632 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11633 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11634 {
11635 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11636 {
11637 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11638 uEventArg = pVmxTransient->uExitIntErrorCode;
11639 }
11640 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11641 switch (enmEvent1)
11642 {
11643 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11644 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11645 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11646 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11647 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11648 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11649 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11650 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11651 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11652 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11653 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11654 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11655 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11656 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11657 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11658 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11659 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11660 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11661 default: break;
11662 }
11663 }
11664 else
11665 AssertFailed();
11666 break;
11667
11668 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11669 uEventArg = idxVector;
11670 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11671 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11672 break;
11673 }
11674 break;
11675 }
11676
11677 case VMX_EXIT_TRIPLE_FAULT:
11678 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11679 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11680 break;
11681 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11682 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11683 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11684 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11685 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11686
11687 /* Instruction specific VM-exits: */
11688 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11689 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11690 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11691 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11692 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11693 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11694 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11695 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11696 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11697 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11698 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11699 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11700 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11701 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11702 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11703 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11704 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11705 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11706 case VMX_EXIT_MOV_CRX:
11707 hmR0VmxReadExitQualVmcs(pVmxTransient);
11708 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11709 SET_BOTH(CRX_READ);
11710 else
11711 SET_BOTH(CRX_WRITE);
11712 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11713 break;
11714 case VMX_EXIT_MOV_DRX:
11715 hmR0VmxReadExitQualVmcs(pVmxTransient);
11716 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11717 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11718 SET_BOTH(DRX_READ);
11719 else
11720 SET_BOTH(DRX_WRITE);
11721 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11722 break;
11723 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11724 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11725 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11726 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11727 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11728 case VMX_EXIT_GDTR_IDTR_ACCESS:
11729 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11730 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11731 {
11732 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11733 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11734 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11735 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11736 }
11737 break;
11738
11739 case VMX_EXIT_LDTR_TR_ACCESS:
11740 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11741 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11742 {
11743 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11744 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11745 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11746 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11747 }
11748 break;
11749
11750 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11751 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11752 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11753 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11754 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11755 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11756 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11757 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11758 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11759 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11760 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11761
11762 /* Events that aren't relevant at this point. */
11763 case VMX_EXIT_EXT_INT:
11764 case VMX_EXIT_INT_WINDOW:
11765 case VMX_EXIT_NMI_WINDOW:
11766 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11767 case VMX_EXIT_PREEMPT_TIMER:
11768 case VMX_EXIT_IO_INSTR:
11769 break;
11770
11771 /* Errors and unexpected events. */
11772 case VMX_EXIT_INIT_SIGNAL:
11773 case VMX_EXIT_SIPI:
11774 case VMX_EXIT_IO_SMI:
11775 case VMX_EXIT_SMI:
11776 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11777 case VMX_EXIT_ERR_MSR_LOAD:
11778 case VMX_EXIT_ERR_MACHINE_CHECK:
11779 case VMX_EXIT_PML_FULL:
11780 case VMX_EXIT_VIRTUALIZED_EOI:
11781 break;
11782
11783 default:
11784 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11785 break;
11786 }
11787#undef SET_BOTH
11788#undef SET_EXIT
11789
11790 /*
11791 * Dtrace tracepoints go first. We do them here at once so we don't
11792 * have to copy the guest state saving and stuff a few dozen times.
11793 * Down side is that we've got to repeat the switch, though this time
11794 * we use enmEvent since the probes are a subset of what DBGF does.
11795 */
11796 if (fDtrace1 || fDtrace2)
11797 {
11798 hmR0VmxReadExitQualVmcs(pVmxTransient);
11799 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11800 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11801 switch (enmEvent1)
11802 {
11803 /** @todo consider which extra parameters would be helpful for each probe. */
11804 case DBGFEVENT_END: break;
11805 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11806 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11807 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11808 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11809 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11810 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11811 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11812 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11813 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11814 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11815 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11816 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11817 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11818 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11819 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11820 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11821 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11822 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11823 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11824 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11825 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11826 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11827 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11828 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11829 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11830 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11831 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11832 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11833 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11834 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11835 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11836 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11837 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11838 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11839 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11840 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11841 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11842 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11843 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11844 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11845 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11846 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11847 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11848 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11849 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11850 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11851 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11852 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11853 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11854 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11855 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11856 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11857 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11858 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11859 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11860 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11861 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11862 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11863 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11864 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11865 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11866 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11867 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11868 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11869 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11870 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11871 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11872 }
11873 switch (enmEvent2)
11874 {
11875 /** @todo consider which extra parameters would be helpful for each probe. */
11876 case DBGFEVENT_END: break;
11877 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11878 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11879 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11880 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11881 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11882 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11883 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11884 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11885 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11886 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11887 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11888 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11889 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11890 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11891 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11892 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11893 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11894 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11895 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11896 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11897 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11898 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11899 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11900 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11901 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11902 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11903 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11904 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11905 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11906 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11907 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11908 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11909 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11910 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11911 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11912 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11913 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11914 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11915 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11916 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11917 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11918 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11919 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11920 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11921 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11922 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11923 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11924 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11925 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11926 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11927 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11928 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11929 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11930 }
11931 }
11932
11933 /*
11934 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11935 * the DBGF call will do a full check).
11936 *
11937 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11938 * Note! If we have to events, we prioritize the first, i.e. the instruction
11939 * one, in order to avoid event nesting.
11940 */
11941 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11942 if ( enmEvent1 != DBGFEVENT_END
11943 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11944 {
11945 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11946 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11947 if (rcStrict != VINF_SUCCESS)
11948 return rcStrict;
11949 }
11950 else if ( enmEvent2 != DBGFEVENT_END
11951 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11952 {
11953 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11954 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11955 if (rcStrict != VINF_SUCCESS)
11956 return rcStrict;
11957 }
11958
11959 return VINF_SUCCESS;
11960}
11961
11962
11963/**
11964 * Single-stepping VM-exit filtering.
11965 *
11966 * This is preprocessing the VM-exits and deciding whether we've gotten far
11967 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11968 * handling is performed.
11969 *
11970 * @returns Strict VBox status code (i.e. informational status codes too).
11971 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11972 * @param pVmxTransient The VMX-transient structure.
11973 * @param pDbgState The debug state.
11974 */
11975DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11976{
11977 /*
11978 * Expensive (saves context) generic dtrace VM-exit probe.
11979 */
11980 uint32_t const uExitReason = pVmxTransient->uExitReason;
11981 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11982 { /* more likely */ }
11983 else
11984 {
11985 hmR0VmxReadExitQualVmcs(pVmxTransient);
11986 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11987 AssertRC(rc);
11988 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11989 }
11990
11991 /*
11992 * Check for host NMI, just to get that out of the way.
11993 */
11994 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11995 { /* normally likely */ }
11996 else
11997 {
11998 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11999 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12000 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12001 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12002 }
12003
12004 /*
12005 * Check for single stepping event if we're stepping.
12006 */
12007 if (pVCpu->hm.s.fSingleInstruction)
12008 {
12009 switch (uExitReason)
12010 {
12011 case VMX_EXIT_MTF:
12012 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12013
12014 /* Various events: */
12015 case VMX_EXIT_XCPT_OR_NMI:
12016 case VMX_EXIT_EXT_INT:
12017 case VMX_EXIT_TRIPLE_FAULT:
12018 case VMX_EXIT_INT_WINDOW:
12019 case VMX_EXIT_NMI_WINDOW:
12020 case VMX_EXIT_TASK_SWITCH:
12021 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12022 case VMX_EXIT_APIC_ACCESS:
12023 case VMX_EXIT_EPT_VIOLATION:
12024 case VMX_EXIT_EPT_MISCONFIG:
12025 case VMX_EXIT_PREEMPT_TIMER:
12026
12027 /* Instruction specific VM-exits: */
12028 case VMX_EXIT_CPUID:
12029 case VMX_EXIT_GETSEC:
12030 case VMX_EXIT_HLT:
12031 case VMX_EXIT_INVD:
12032 case VMX_EXIT_INVLPG:
12033 case VMX_EXIT_RDPMC:
12034 case VMX_EXIT_RDTSC:
12035 case VMX_EXIT_RSM:
12036 case VMX_EXIT_VMCALL:
12037 case VMX_EXIT_VMCLEAR:
12038 case VMX_EXIT_VMLAUNCH:
12039 case VMX_EXIT_VMPTRLD:
12040 case VMX_EXIT_VMPTRST:
12041 case VMX_EXIT_VMREAD:
12042 case VMX_EXIT_VMRESUME:
12043 case VMX_EXIT_VMWRITE:
12044 case VMX_EXIT_VMXOFF:
12045 case VMX_EXIT_VMXON:
12046 case VMX_EXIT_MOV_CRX:
12047 case VMX_EXIT_MOV_DRX:
12048 case VMX_EXIT_IO_INSTR:
12049 case VMX_EXIT_RDMSR:
12050 case VMX_EXIT_WRMSR:
12051 case VMX_EXIT_MWAIT:
12052 case VMX_EXIT_MONITOR:
12053 case VMX_EXIT_PAUSE:
12054 case VMX_EXIT_GDTR_IDTR_ACCESS:
12055 case VMX_EXIT_LDTR_TR_ACCESS:
12056 case VMX_EXIT_INVEPT:
12057 case VMX_EXIT_RDTSCP:
12058 case VMX_EXIT_INVVPID:
12059 case VMX_EXIT_WBINVD:
12060 case VMX_EXIT_XSETBV:
12061 case VMX_EXIT_RDRAND:
12062 case VMX_EXIT_INVPCID:
12063 case VMX_EXIT_VMFUNC:
12064 case VMX_EXIT_RDSEED:
12065 case VMX_EXIT_XSAVES:
12066 case VMX_EXIT_XRSTORS:
12067 {
12068 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12069 AssertRCReturn(rc, rc);
12070 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12071 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12072 return VINF_EM_DBG_STEPPED;
12073 break;
12074 }
12075
12076 /* Errors and unexpected events: */
12077 case VMX_EXIT_INIT_SIGNAL:
12078 case VMX_EXIT_SIPI:
12079 case VMX_EXIT_IO_SMI:
12080 case VMX_EXIT_SMI:
12081 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12082 case VMX_EXIT_ERR_MSR_LOAD:
12083 case VMX_EXIT_ERR_MACHINE_CHECK:
12084 case VMX_EXIT_PML_FULL:
12085 case VMX_EXIT_VIRTUALIZED_EOI:
12086 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12087 break;
12088
12089 default:
12090 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12091 break;
12092 }
12093 }
12094
12095 /*
12096 * Check for debugger event breakpoints and dtrace probes.
12097 */
12098 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12099 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12100 {
12101 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12102 if (rcStrict != VINF_SUCCESS)
12103 return rcStrict;
12104 }
12105
12106 /*
12107 * Normal processing.
12108 */
12109#ifdef HMVMX_USE_FUNCTION_TABLE
12110 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12111#else
12112 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12113#endif
12114}
12115
12116
12117/**
12118 * Single steps guest code using hardware-assisted VMX.
12119 *
12120 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12121 * but single-stepping through the hypervisor debugger.
12122 *
12123 * @returns Strict VBox status code (i.e. informational status codes too).
12124 * @param pVCpu The cross context virtual CPU structure.
12125 * @param pcLoops Pointer to the number of executed loops.
12126 *
12127 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12128 */
12129static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12130{
12131 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12132 Assert(pcLoops);
12133 Assert(*pcLoops <= cMaxResumeLoops);
12134
12135 VMXTRANSIENT VmxTransient;
12136 RT_ZERO(VmxTransient);
12137 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12138
12139 /* Set HMCPU indicators. */
12140 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12141 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12142 pVCpu->hm.s.fDebugWantRdTscExit = false;
12143 pVCpu->hm.s.fUsingDebugLoop = true;
12144
12145 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12146 VMXRUNDBGSTATE DbgState;
12147 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12148 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12149
12150 /*
12151 * The loop.
12152 */
12153 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12154 for (;;)
12155 {
12156 Assert(!HMR0SuspendPending());
12157 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12158 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12159 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12160
12161 /* Set up VM-execution controls the next two can respond to. */
12162 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12163
12164 /*
12165 * Preparatory work for running guest code, this may force us to
12166 * return to ring-3.
12167 *
12168 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12169 */
12170 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12171 if (rcStrict != VINF_SUCCESS)
12172 break;
12173
12174 /* Interrupts are disabled at this point! */
12175 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12176
12177 /* Override any obnoxious code in the above two calls. */
12178 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12179
12180 /*
12181 * Finally execute the guest.
12182 */
12183 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12184
12185 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12186 /* Interrupts are re-enabled at this point! */
12187
12188 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12189 if (RT_SUCCESS(rcRun))
12190 { /* very likely */ }
12191 else
12192 {
12193 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12194 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12195 return rcRun;
12196 }
12197
12198 /* Profile the VM-exit. */
12199 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12200 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12201 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12202 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12203 HMVMX_START_EXIT_DISPATCH_PROF();
12204
12205 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12206
12207 /*
12208 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12209 */
12210 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12211 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12212 if (rcStrict != VINF_SUCCESS)
12213 break;
12214 if (++(*pcLoops) > cMaxResumeLoops)
12215 {
12216 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12217 rcStrict = VINF_EM_RAW_INTERRUPT;
12218 break;
12219 }
12220
12221 /*
12222 * Stepping: Did the RIP change, if so, consider it a single step.
12223 * Otherwise, make sure one of the TFs gets set.
12224 */
12225 if (fStepping)
12226 {
12227 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12228 AssertRC(rc);
12229 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12230 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12231 {
12232 rcStrict = VINF_EM_DBG_STEPPED;
12233 break;
12234 }
12235 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12236 }
12237
12238 /*
12239 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12240 */
12241 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12242 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12243 }
12244
12245 /*
12246 * Clear the X86_EFL_TF if necessary.
12247 */
12248 if (pVCpu->hm.s.fClearTrapFlag)
12249 {
12250 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12251 AssertRC(rc);
12252 pVCpu->hm.s.fClearTrapFlag = false;
12253 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12254 }
12255 /** @todo there seems to be issues with the resume flag when the monitor trap
12256 * flag is pending without being used. Seen early in bios init when
12257 * accessing APIC page in protected mode. */
12258
12259 /*
12260 * Restore VM-exit control settings as we may not re-enter this function the
12261 * next time around.
12262 */
12263 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12264
12265 /* Restore HMCPU indicators. */
12266 pVCpu->hm.s.fUsingDebugLoop = false;
12267 pVCpu->hm.s.fDebugWantRdTscExit = false;
12268 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12269
12270 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12271 return rcStrict;
12272}
12273
12274
12275/** @} */
12276
12277
12278/**
12279 * Checks if any expensive dtrace probes are enabled and we should go to the
12280 * debug loop.
12281 *
12282 * @returns true if we should use debug loop, false if not.
12283 */
12284static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12285{
12286 /* It's probably faster to OR the raw 32-bit counter variables together.
12287 Since the variables are in an array and the probes are next to one
12288 another (more or less), we have good locality. So, better read
12289 eight-nine cache lines ever time and only have one conditional, than
12290 128+ conditionals, right? */
12291 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12292 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12293 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12294 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12295 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12296 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12297 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12298 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12299 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12300 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12301 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12302 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12303 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12304 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12305 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12306 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12307 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12308 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12309 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12310 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12311 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12312 ) != 0
12313 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12314 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12315 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12316 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12317 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12318 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12319 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12320 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12321 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12322 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12323 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12324 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12325 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12326 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12327 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12328 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12329 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12330 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12331 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12332 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12333 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12334 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12335 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12336 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12337 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12338 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12339 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12340 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12341 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12342 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12343 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12344 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12345 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12346 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12347 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12348 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12349 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12350 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12351 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12352 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12353 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12354 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12355 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12356 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12357 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12358 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12359 ) != 0
12360 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12361 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12362 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12363 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12364 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12365 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12366 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12367 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12368 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12369 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12370 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12371 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12372 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12373 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12374 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12375 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12376 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12377 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12378 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12379 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12380 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12381 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12382 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12383 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12384 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12385 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12386 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12387 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12388 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12389 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12390 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12391 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12392 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12393 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12394 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12395 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12396 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12397 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12398 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12399 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12400 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12401 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12402 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12403 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12404 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12405 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12406 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12407 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12408 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12409 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12410 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12411 ) != 0;
12412}
12413
12414
12415/**
12416 * Runs the guest using hardware-assisted VMX.
12417 *
12418 * @returns Strict VBox status code (i.e. informational status codes too).
12419 * @param pVCpu The cross context virtual CPU structure.
12420 */
12421VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12422{
12423 AssertPtr(pVCpu);
12424 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12425 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12426 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12427 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12428
12429 VBOXSTRICTRC rcStrict;
12430 uint32_t cLoops = 0;
12431 for (;;)
12432 {
12433#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12434 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12435#else
12436 NOREF(pCtx);
12437 bool const fInNestedGuestMode = false;
12438#endif
12439 if (!fInNestedGuestMode)
12440 {
12441 if ( !pVCpu->hm.s.fUseDebugLoop
12442 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12443 && !DBGFIsStepping(pVCpu)
12444 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12445 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12446 else
12447 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12448 }
12449#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12450 else
12451 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12452
12453 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12454 {
12455 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12456 continue;
12457 }
12458 if (rcStrict == VINF_VMX_VMEXIT)
12459 {
12460 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12461 continue;
12462 }
12463#endif
12464 break;
12465 }
12466
12467 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12468 switch (rcLoop)
12469 {
12470 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12471 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12472 }
12473
12474 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12475 if (RT_FAILURE(rc2))
12476 {
12477 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12478 rcStrict = rc2;
12479 }
12480 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12481 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12482 return rcStrict;
12483}
12484
12485
12486#ifndef HMVMX_USE_FUNCTION_TABLE
12487/**
12488 * Handles a guest VM-exit from hardware-assisted VMX execution.
12489 *
12490 * @returns Strict VBox status code (i.e. informational status codes too).
12491 * @param pVCpu The cross context virtual CPU structure.
12492 * @param pVmxTransient The VMX-transient structure.
12493 */
12494DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12495{
12496#ifdef DEBUG_ramshankar
12497# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12498 do { \
12499 if (a_fSave != 0) \
12500 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12501 VBOXSTRICTRC rcStrict = a_CallExpr; \
12502 if (a_fSave != 0) \
12503 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12504 return rcStrict; \
12505 } while (0)
12506#else
12507# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12508#endif
12509 uint32_t const uExitReason = pVmxTransient->uExitReason;
12510 switch (uExitReason)
12511 {
12512 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12513 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12514 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12515 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12516 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12517 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12518 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12519 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12520 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12521 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12522 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12523 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12524 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12525 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12526 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12527 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12528 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12529 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12530 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12531 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12532 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12533 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12534 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12535 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12536 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12537 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12538 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12539 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12540 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12541 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12542#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12543 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12544 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12545 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12546 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12547 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12548 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12549 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12550 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12551 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12552 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12553 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12554#else
12555 case VMX_EXIT_VMCLEAR:
12556 case VMX_EXIT_VMLAUNCH:
12557 case VMX_EXIT_VMPTRLD:
12558 case VMX_EXIT_VMPTRST:
12559 case VMX_EXIT_VMREAD:
12560 case VMX_EXIT_VMRESUME:
12561 case VMX_EXIT_VMWRITE:
12562 case VMX_EXIT_VMXOFF:
12563 case VMX_EXIT_VMXON:
12564 case VMX_EXIT_INVVPID:
12565 case VMX_EXIT_INVEPT:
12566 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12567#endif
12568
12569 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12570 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12571 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12572
12573 case VMX_EXIT_INIT_SIGNAL:
12574 case VMX_EXIT_SIPI:
12575 case VMX_EXIT_IO_SMI:
12576 case VMX_EXIT_SMI:
12577 case VMX_EXIT_ERR_MSR_LOAD:
12578 case VMX_EXIT_ERR_MACHINE_CHECK:
12579 case VMX_EXIT_PML_FULL:
12580 case VMX_EXIT_VIRTUALIZED_EOI:
12581 case VMX_EXIT_GDTR_IDTR_ACCESS:
12582 case VMX_EXIT_LDTR_TR_ACCESS:
12583 case VMX_EXIT_APIC_WRITE:
12584 case VMX_EXIT_RDRAND:
12585 case VMX_EXIT_RSM:
12586 case VMX_EXIT_VMFUNC:
12587 case VMX_EXIT_ENCLS:
12588 case VMX_EXIT_RDSEED:
12589 case VMX_EXIT_XSAVES:
12590 case VMX_EXIT_XRSTORS:
12591 case VMX_EXIT_UMWAIT:
12592 case VMX_EXIT_TPAUSE:
12593 default:
12594 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12595 }
12596#undef VMEXIT_CALL_RET
12597}
12598#endif /* !HMVMX_USE_FUNCTION_TABLE */
12599
12600
12601#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12602/**
12603 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12604 *
12605 * @returns Strict VBox status code (i.e. informational status codes too).
12606 * @param pVCpu The cross context virtual CPU structure.
12607 * @param pVmxTransient The VMX-transient structure.
12608 */
12609DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12610{
12611 /** @todo NSTVMX: Remove after debugging page-fault issue. */
12612#ifdef DEBUG_ramshankar
12613 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12614 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64 eflags=%#RX32 cr3=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
12615 pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.cr3));
12616#endif
12617
12618 uint32_t const uExitReason = pVmxTransient->uExitReason;
12619 switch (uExitReason)
12620 {
12621 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12622 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12623 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12624 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12625 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12626
12627 /*
12628 * We shouldn't direct host physical interrupts to the nested-guest.
12629 */
12630 case VMX_EXIT_EXT_INT:
12631 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12632
12633 /*
12634 * Instructions that cause VM-exits unconditionally or the condition is
12635 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12636 * happens, it's guaranteed to be a nested-guest VM-exit).
12637 *
12638 * - Provides VM-exit instruction length ONLY.
12639 */
12640 case VMX_EXIT_CPUID: /* Unconditional. */
12641 case VMX_EXIT_VMCALL:
12642 case VMX_EXIT_GETSEC:
12643 case VMX_EXIT_INVD:
12644 case VMX_EXIT_XSETBV:
12645 case VMX_EXIT_VMLAUNCH:
12646 case VMX_EXIT_VMRESUME:
12647 case VMX_EXIT_VMXOFF:
12648 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
12649 case VMX_EXIT_VMFUNC:
12650 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12651
12652 /*
12653 * Instructions that cause VM-exits unconditionally or the condition is
12654 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12655 * happens, it's guaranteed to be a nested-guest VM-exit).
12656 *
12657 * - Provides VM-exit instruction length.
12658 * - Provides VM-exit information.
12659 * - Optionally provides Exit qualification.
12660 *
12661 * Since Exit qualification is 0 for all VM-exits where it is not
12662 * applicable, reading and passing it to the guest should produce
12663 * defined behavior.
12664 *
12665 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12666 */
12667 case VMX_EXIT_INVEPT: /* Unconditional. */
12668 case VMX_EXIT_INVVPID:
12669 case VMX_EXIT_VMCLEAR:
12670 case VMX_EXIT_VMPTRLD:
12671 case VMX_EXIT_VMPTRST:
12672 case VMX_EXIT_VMXON:
12673 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
12674 case VMX_EXIT_LDTR_TR_ACCESS:
12675 case VMX_EXIT_RDRAND:
12676 case VMX_EXIT_RDSEED:
12677 case VMX_EXIT_XSAVES:
12678 case VMX_EXIT_XRSTORS:
12679 case VMX_EXIT_UMWAIT:
12680 case VMX_EXIT_TPAUSE:
12681 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12682
12683 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12684 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12685 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12686 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12687 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12688 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12689 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12690 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12691 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12692 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12693 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12694 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12695 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12696 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12697 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12698 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12699 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12700 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12701 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12702
12703 case VMX_EXIT_PREEMPT_TIMER:
12704 {
12705 /** @todo NSTVMX: Preempt timer. */
12706 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12707 }
12708
12709 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12710 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12711
12712 case VMX_EXIT_VMREAD:
12713 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12714
12715 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12716 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12717
12718 case VMX_EXIT_INIT_SIGNAL:
12719 case VMX_EXIT_SIPI:
12720 case VMX_EXIT_IO_SMI:
12721 case VMX_EXIT_SMI:
12722 case VMX_EXIT_ERR_MSR_LOAD:
12723 case VMX_EXIT_ERR_MACHINE_CHECK:
12724 case VMX_EXIT_PML_FULL:
12725 case VMX_EXIT_RSM:
12726 default:
12727 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12728 }
12729}
12730#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12731
12732
12733/** @name VM-exit helpers.
12734 * @{
12735 */
12736/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12737/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12738/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12739
12740/** Macro for VM-exits called unexpectedly. */
12741#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12742 do { \
12743 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12744 return VERR_VMX_UNEXPECTED_EXIT; \
12745 } while (0)
12746
12747#ifdef VBOX_STRICT
12748/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12749# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12750 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12751
12752# define HMVMX_ASSERT_PREEMPT_CPUID() \
12753 do { \
12754 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12755 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12756 } while (0)
12757
12758# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12759 do { \
12760 AssertPtr((a_pVCpu)); \
12761 AssertPtr((a_pVmxTransient)); \
12762 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12763 Assert((a_pVmxTransient)->pVmcsInfo); \
12764 Assert(ASMIntAreEnabled()); \
12765 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12766 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12767 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12768 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12769 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12770 HMVMX_ASSERT_PREEMPT_CPUID(); \
12771 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12772 } while (0)
12773
12774# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12775 do { \
12776 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12777 Assert((a_pVmxTransient)->fIsNestedGuest); \
12778 } while (0)
12779
12780# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12781 do { \
12782 Log4Func(("\n")); \
12783 } while (0)
12784#else
12785# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12786 do { \
12787 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12788 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12789 } while (0)
12790
12791# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12792 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12793
12794# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12795#endif
12796
12797#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12798/** Macro that does the necessary privilege checks and intercepted VM-exits for
12799 * guests that attempted to execute a VMX instruction. */
12800# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12801 do \
12802 { \
12803 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12804 if (rcStrictTmp == VINF_SUCCESS) \
12805 { /* likely */ } \
12806 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12807 { \
12808 Assert((a_pVCpu)->hm.s.Event.fPending); \
12809 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12810 return VINF_SUCCESS; \
12811 } \
12812 else \
12813 { \
12814 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12815 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12816 } \
12817 } while (0)
12818
12819/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12820# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12821 do \
12822 { \
12823 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12824 (a_pGCPtrEffAddr)); \
12825 if (rcStrictTmp == VINF_SUCCESS) \
12826 { /* likely */ } \
12827 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12828 { \
12829 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12830 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12831 NOREF(uXcptTmp); \
12832 return VINF_SUCCESS; \
12833 } \
12834 else \
12835 { \
12836 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12837 return rcStrictTmp; \
12838 } \
12839 } while (0)
12840#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12841
12842
12843/**
12844 * Advances the guest RIP by the specified number of bytes.
12845 *
12846 * @param pVCpu The cross context virtual CPU structure.
12847 * @param cbInstr Number of bytes to advance the RIP by.
12848 *
12849 * @remarks No-long-jump zone!!!
12850 */
12851DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12852{
12853 /* Advance the RIP. */
12854 pVCpu->cpum.GstCtx.rip += cbInstr;
12855 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12856
12857 /* Update interrupt inhibition. */
12858 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12859 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12860 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12861}
12862
12863
12864/**
12865 * Advances the guest RIP after reading it from the VMCS.
12866 *
12867 * @returns VBox status code, no informational status codes.
12868 * @param pVCpu The cross context virtual CPU structure.
12869 * @param pVmxTransient The VMX-transient structure.
12870 *
12871 * @remarks No-long-jump zone!!!
12872 */
12873static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12874{
12875 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12876 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12877 AssertRCReturn(rc, rc);
12878
12879 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
12880 return VINF_SUCCESS;
12881}
12882
12883
12884/**
12885 * Handle a condition that occurred while delivering an event through the guest or
12886 * nested-guest IDT.
12887 *
12888 * @returns Strict VBox status code (i.e. informational status codes too).
12889 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12890 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12891 * to continue execution of the guest which will delivery the \#DF.
12892 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12893 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12894 *
12895 * @param pVCpu The cross context virtual CPU structure.
12896 * @param pVmxTransient The VMX-transient structure.
12897 *
12898 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12899 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12900 * is due to an EPT violation, PML full or SPP-related event.
12901 *
12902 * @remarks No-long-jump zone!!!
12903 */
12904static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12905{
12906 Assert(!pVCpu->hm.s.Event.fPending);
12907 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12908 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12909 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12910 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12911 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12912
12913 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12914 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12915 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12916 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12917 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12918 {
12919 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12920 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12921
12922 /*
12923 * If the event was a software interrupt (generated with INT n) or a software exception
12924 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12925 * can handle the VM-exit and continue guest execution which will re-execute the
12926 * instruction rather than re-injecting the exception, as that can cause premature
12927 * trips to ring-3 before injection and involve TRPM which currently has no way of
12928 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12929 * the problem).
12930 */
12931 IEMXCPTRAISE enmRaise;
12932 IEMXCPTRAISEINFO fRaiseInfo;
12933 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12934 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12935 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12936 {
12937 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12938 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12939 }
12940 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12941 {
12942 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12943 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12944 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12945
12946 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12947 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12948
12949 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12950
12951 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12952 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12953 {
12954 pVmxTransient->fVectoringPF = true;
12955 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12956 }
12957 }
12958 else
12959 {
12960 /*
12961 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12962 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12963 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12964 */
12965 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12966 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12967 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12968 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12969 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12970 }
12971
12972 /*
12973 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12974 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12975 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12976 * subsequent VM-entry would fail, see @bugref{7445}.
12977 *
12978 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12979 */
12980 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12981 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12982 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12983 && CPUMIsGuestNmiBlocking(pVCpu))
12984 {
12985 CPUMSetGuestNmiBlocking(pVCpu, false);
12986 }
12987
12988 switch (enmRaise)
12989 {
12990 case IEMXCPTRAISE_CURRENT_XCPT:
12991 {
12992 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
12993 Assert(rcStrict == VINF_SUCCESS);
12994 break;
12995 }
12996
12997 case IEMXCPTRAISE_PREV_EVENT:
12998 {
12999 uint32_t u32ErrCode;
13000 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13001 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13002 else
13003 u32ErrCode = 0;
13004
13005 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13006 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13007 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13008 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13009
13010 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13011 pVCpu->hm.s.Event.u32ErrCode));
13012 Assert(rcStrict == VINF_SUCCESS);
13013 break;
13014 }
13015
13016 case IEMXCPTRAISE_REEXEC_INSTR:
13017 Assert(rcStrict == VINF_SUCCESS);
13018 break;
13019
13020 case IEMXCPTRAISE_DOUBLE_FAULT:
13021 {
13022 /*
13023 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13024 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13025 */
13026 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13027 {
13028 pVmxTransient->fVectoringDoublePF = true;
13029 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13030 pVCpu->cpum.GstCtx.cr2));
13031 rcStrict = VINF_SUCCESS;
13032 }
13033 else
13034 {
13035 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13036 hmR0VmxSetPendingXcptDF(pVCpu);
13037 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13038 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13039 rcStrict = VINF_HM_DOUBLE_FAULT;
13040 }
13041 break;
13042 }
13043
13044 case IEMXCPTRAISE_TRIPLE_FAULT:
13045 {
13046 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13047 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13048 rcStrict = VINF_EM_RESET;
13049 break;
13050 }
13051
13052 case IEMXCPTRAISE_CPU_HANG:
13053 {
13054 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13055 rcStrict = VERR_EM_GUEST_CPU_HANG;
13056 break;
13057 }
13058
13059 default:
13060 {
13061 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13062 rcStrict = VERR_VMX_IPE_2;
13063 break;
13064 }
13065 }
13066 }
13067 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13068 && !CPUMIsGuestNmiBlocking(pVCpu))
13069 {
13070 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13071 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13072 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13073 {
13074 /*
13075 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13076 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13077 * that NMIs remain blocked until the IRET execution is completed.
13078 *
13079 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13080 */
13081 CPUMSetGuestNmiBlocking(pVCpu, true);
13082 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13083 }
13084 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13085 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13086 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13087 {
13088 /*
13089 * Execution of IRET caused an EPT violation, page-modification log-full event or
13090 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13091 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13092 * that NMIs remain blocked until the IRET execution is completed.
13093 *
13094 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13095 */
13096 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13097 {
13098 CPUMSetGuestNmiBlocking(pVCpu, true);
13099 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13100 }
13101 }
13102 }
13103
13104 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13105 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13106 return rcStrict;
13107}
13108
13109
13110#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13111/**
13112 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13113 * guest attempting to execute a VMX instruction.
13114 *
13115 * @returns Strict VBox status code (i.e. informational status codes too).
13116 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13117 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13118 *
13119 * @param pVCpu The cross context virtual CPU structure.
13120 * @param uExitReason The VM-exit reason.
13121 *
13122 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13123 * @remarks No-long-jump zone!!!
13124 */
13125static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13126{
13127 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13128 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13129
13130 /*
13131 * The physical CPU would have already checked the CPU mode/code segment.
13132 * We shall just assert here for paranoia.
13133 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13134 */
13135 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13136 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13137 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13138
13139 if (uExitReason == VMX_EXIT_VMXON)
13140 {
13141 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13142
13143 /*
13144 * We check CR4.VMXE because it is required to be always set while in VMX operation
13145 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13146 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13147 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13148 */
13149 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13150 {
13151 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13152 hmR0VmxSetPendingXcptUD(pVCpu);
13153 return VINF_HM_PENDING_XCPT;
13154 }
13155 }
13156 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13157 {
13158 /*
13159 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13160 * (other than VMXON), we need to raise a #UD.
13161 */
13162 Log4Func(("Not in VMX root mode -> #UD\n"));
13163 hmR0VmxSetPendingXcptUD(pVCpu);
13164 return VINF_HM_PENDING_XCPT;
13165 }
13166
13167 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13168 return VINF_SUCCESS;
13169}
13170
13171
13172/**
13173 * Decodes the memory operand of an instruction that caused a VM-exit.
13174 *
13175 * The Exit qualification field provides the displacement field for memory
13176 * operand instructions, if any.
13177 *
13178 * @returns Strict VBox status code (i.e. informational status codes too).
13179 * @retval VINF_SUCCESS if the operand was successfully decoded.
13180 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13181 * operand.
13182 * @param pVCpu The cross context virtual CPU structure.
13183 * @param uExitInstrInfo The VM-exit instruction information field.
13184 * @param enmMemAccess The memory operand's access type (read or write).
13185 * @param GCPtrDisp The instruction displacement field, if any. For
13186 * RIP-relative addressing pass RIP + displacement here.
13187 * @param pGCPtrMem Where to store the effective destination memory address.
13188 *
13189 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13190 * virtual-8086 mode hence skips those checks while verifying if the
13191 * segment is valid.
13192 */
13193static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13194 PRTGCPTR pGCPtrMem)
13195{
13196 Assert(pGCPtrMem);
13197 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13198 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13199 | CPUMCTX_EXTRN_CR0);
13200
13201 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13202 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13203 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13204
13205 VMXEXITINSTRINFO ExitInstrInfo;
13206 ExitInstrInfo.u = uExitInstrInfo;
13207 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13208 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13209 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13210 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13211 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13212 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13213 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13214 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13215 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13216
13217 /*
13218 * Validate instruction information.
13219 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13220 */
13221 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13222 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13223 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13224 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13225 AssertLogRelMsgReturn(fIsMemOperand,
13226 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13227
13228 /*
13229 * Compute the complete effective address.
13230 *
13231 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13232 * See AMD spec. 4.5.2 "Segment Registers".
13233 */
13234 RTGCPTR GCPtrMem = GCPtrDisp;
13235 if (fBaseRegValid)
13236 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13237 if (fIdxRegValid)
13238 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13239
13240 RTGCPTR const GCPtrOff = GCPtrMem;
13241 if ( !fIsLongMode
13242 || iSegReg >= X86_SREG_FS)
13243 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13244 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13245
13246 /*
13247 * Validate effective address.
13248 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13249 */
13250 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13251 Assert(cbAccess > 0);
13252 if (fIsLongMode)
13253 {
13254 if (X86_IS_CANONICAL(GCPtrMem))
13255 {
13256 *pGCPtrMem = GCPtrMem;
13257 return VINF_SUCCESS;
13258 }
13259
13260 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13261 * "Data Limit Checks in 64-bit Mode". */
13262 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13263 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13264 return VINF_HM_PENDING_XCPT;
13265 }
13266
13267 /*
13268 * This is a watered down version of iemMemApplySegment().
13269 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13270 * and segment CPL/DPL checks are skipped.
13271 */
13272 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13273 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13274 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13275
13276 /* Check if the segment is present and usable. */
13277 if ( pSel->Attr.n.u1Present
13278 && !pSel->Attr.n.u1Unusable)
13279 {
13280 Assert(pSel->Attr.n.u1DescType);
13281 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13282 {
13283 /* Check permissions for the data segment. */
13284 if ( enmMemAccess == VMXMEMACCESS_WRITE
13285 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13286 {
13287 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13288 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13289 return VINF_HM_PENDING_XCPT;
13290 }
13291
13292 /* Check limits if it's a normal data segment. */
13293 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13294 {
13295 if ( GCPtrFirst32 > pSel->u32Limit
13296 || GCPtrLast32 > pSel->u32Limit)
13297 {
13298 Log4Func(("Data segment limit exceeded. "
13299 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13300 GCPtrLast32, pSel->u32Limit));
13301 if (iSegReg == X86_SREG_SS)
13302 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13303 else
13304 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13305 return VINF_HM_PENDING_XCPT;
13306 }
13307 }
13308 else
13309 {
13310 /* Check limits if it's an expand-down data segment.
13311 Note! The upper boundary is defined by the B bit, not the G bit! */
13312 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13313 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13314 {
13315 Log4Func(("Expand-down data segment limit exceeded. "
13316 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13317 GCPtrLast32, pSel->u32Limit));
13318 if (iSegReg == X86_SREG_SS)
13319 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13320 else
13321 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13322 return VINF_HM_PENDING_XCPT;
13323 }
13324 }
13325 }
13326 else
13327 {
13328 /* Check permissions for the code segment. */
13329 if ( enmMemAccess == VMXMEMACCESS_WRITE
13330 || ( enmMemAccess == VMXMEMACCESS_READ
13331 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13332 {
13333 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13334 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13335 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13336 return VINF_HM_PENDING_XCPT;
13337 }
13338
13339 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13340 if ( GCPtrFirst32 > pSel->u32Limit
13341 || GCPtrLast32 > pSel->u32Limit)
13342 {
13343 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13344 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13345 if (iSegReg == X86_SREG_SS)
13346 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13347 else
13348 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13349 return VINF_HM_PENDING_XCPT;
13350 }
13351 }
13352 }
13353 else
13354 {
13355 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13356 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13357 return VINF_HM_PENDING_XCPT;
13358 }
13359
13360 *pGCPtrMem = GCPtrMem;
13361 return VINF_SUCCESS;
13362}
13363#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13364
13365
13366/**
13367 * VM-exit helper for LMSW.
13368 */
13369static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13370{
13371 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13372 AssertRCReturn(rc, rc);
13373
13374 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13375 AssertMsg( rcStrict == VINF_SUCCESS
13376 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13377
13378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13379 if (rcStrict == VINF_IEM_RAISED_XCPT)
13380 {
13381 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13382 rcStrict = VINF_SUCCESS;
13383 }
13384
13385 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13386 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13387 return rcStrict;
13388}
13389
13390
13391/**
13392 * VM-exit helper for CLTS.
13393 */
13394static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13395{
13396 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13397 AssertRCReturn(rc, rc);
13398
13399 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13400 AssertMsg( rcStrict == VINF_SUCCESS
13401 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13402
13403 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13404 if (rcStrict == VINF_IEM_RAISED_XCPT)
13405 {
13406 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13407 rcStrict = VINF_SUCCESS;
13408 }
13409
13410 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13411 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13412 return rcStrict;
13413}
13414
13415
13416/**
13417 * VM-exit helper for MOV from CRx (CRx read).
13418 */
13419static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13420{
13421 Assert(iCrReg < 16);
13422 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13423
13424 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13425 AssertRCReturn(rc, rc);
13426
13427 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13428 AssertMsg( rcStrict == VINF_SUCCESS
13429 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13430
13431 if (iGReg == X86_GREG_xSP)
13432 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13433 else
13434 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13435#ifdef VBOX_WITH_STATISTICS
13436 switch (iCrReg)
13437 {
13438 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13439 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13440 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13441 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13442 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13443 }
13444#endif
13445 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13446 return rcStrict;
13447}
13448
13449
13450/**
13451 * VM-exit helper for MOV to CRx (CRx write).
13452 */
13453static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13454{
13455 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13456 AssertRCReturn(rc, rc);
13457
13458 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13459 AssertMsg( rcStrict == VINF_SUCCESS
13460 || rcStrict == VINF_IEM_RAISED_XCPT
13461 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13462
13463 switch (iCrReg)
13464 {
13465 case 0:
13466 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13467 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13468 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13469 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13470 break;
13471
13472 case 2:
13473 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13474 /* Nothing to do here, CR2 it's not part of the VMCS. */
13475 break;
13476
13477 case 3:
13478 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13479 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13480 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13481 break;
13482
13483 case 4:
13484 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13485 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13486 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13487 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13488 break;
13489
13490 case 8:
13491 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13492 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13493 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13494 break;
13495
13496 default:
13497 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13498 break;
13499 }
13500
13501 if (rcStrict == VINF_IEM_RAISED_XCPT)
13502 {
13503 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13504 rcStrict = VINF_SUCCESS;
13505 }
13506 return rcStrict;
13507}
13508
13509
13510/**
13511 * VM-exit exception handler for \#PF (Page-fault exception).
13512 *
13513 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13514 */
13515static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13516{
13517 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13518 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13519 hmR0VmxReadExitQualVmcs(pVmxTransient);
13520
13521 if (!pVM->hm.s.fNestedPaging)
13522 { /* likely */ }
13523 else
13524 {
13525#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13526 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13527#endif
13528 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13529 if (!pVmxTransient->fVectoringDoublePF)
13530 {
13531 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13532 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13533 }
13534 else
13535 {
13536 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13537 Assert(!pVmxTransient->fIsNestedGuest);
13538 hmR0VmxSetPendingXcptDF(pVCpu);
13539 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13540 }
13541 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13542 return VINF_SUCCESS;
13543 }
13544
13545 Assert(!pVmxTransient->fIsNestedGuest);
13546
13547 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13548 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13549 if (pVmxTransient->fVectoringPF)
13550 {
13551 Assert(pVCpu->hm.s.Event.fPending);
13552 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13553 }
13554
13555 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13556 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13557 AssertRCReturn(rc, rc);
13558
13559 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13560 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13561
13562 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13563 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13564
13565 Log4Func(("#PF: rc=%Rrc\n", rc));
13566 if (rc == VINF_SUCCESS)
13567 {
13568 /*
13569 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13570 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13571 */
13572 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13573 TRPMResetTrap(pVCpu);
13574 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13575 return rc;
13576 }
13577
13578 if (rc == VINF_EM_RAW_GUEST_TRAP)
13579 {
13580 if (!pVmxTransient->fVectoringDoublePF)
13581 {
13582 /* It's a guest page fault and needs to be reflected to the guest. */
13583 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
13584 TRPMResetTrap(pVCpu);
13585 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13586 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13587 uGstErrorCode, pVmxTransient->uExitQual);
13588 }
13589 else
13590 {
13591 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13592 TRPMResetTrap(pVCpu);
13593 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13594 hmR0VmxSetPendingXcptDF(pVCpu);
13595 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13596 }
13597
13598 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13599 return VINF_SUCCESS;
13600 }
13601
13602 TRPMResetTrap(pVCpu);
13603 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13604 return rc;
13605}
13606
13607
13608/**
13609 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13610 *
13611 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13612 */
13613static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13614{
13615 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13616 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13617
13618 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13619 AssertRCReturn(rc, rc);
13620
13621 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13622 {
13623 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13624 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13625
13626 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13627 * provides VM-exit instruction length. If this causes problem later,
13628 * disassemble the instruction like it's done on AMD-V. */
13629 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13630 AssertRCReturn(rc2, rc2);
13631 return rc;
13632 }
13633
13634 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13635 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13636 return VINF_SUCCESS;
13637}
13638
13639
13640/**
13641 * VM-exit exception handler for \#BP (Breakpoint exception).
13642 *
13643 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13644 */
13645static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13646{
13647 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13648 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13649
13650 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13651 AssertRCReturn(rc, rc);
13652
13653 if (!pVmxTransient->fIsNestedGuest)
13654 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13655 else
13656 rc = VINF_EM_RAW_GUEST_TRAP;
13657
13658 if (rc == VINF_EM_RAW_GUEST_TRAP)
13659 {
13660 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13661 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13662 rc = VINF_SUCCESS;
13663 }
13664
13665 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13666 return rc;
13667}
13668
13669
13670/**
13671 * VM-exit exception handler for \#AC (Alignment-check exception).
13672 *
13673 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13674 */
13675static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13676{
13677 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13678 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13679
13680 /* Re-inject it. We'll detect any nesting before getting here. */
13681 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13682 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13683 return VINF_SUCCESS;
13684}
13685
13686
13687/**
13688 * VM-exit exception handler for \#DB (Debug exception).
13689 *
13690 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13691 */
13692static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13693{
13694 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13695 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13696
13697 /*
13698 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13699 */
13700 hmR0VmxReadExitQualVmcs(pVmxTransient);
13701
13702 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13703 uint64_t const uDR6 = X86_DR6_INIT_VAL
13704 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13705 | X86_DR6_BD | X86_DR6_BS));
13706
13707 int rc;
13708 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13709 if (!pVmxTransient->fIsNestedGuest)
13710 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13711 else
13712 rc = VINF_EM_RAW_GUEST_TRAP;
13713 Log6Func(("rc=%Rrc\n", rc));
13714 if (rc == VINF_EM_RAW_GUEST_TRAP)
13715 {
13716 /*
13717 * The exception was for the guest. Update DR6, DR7.GD and
13718 * IA32_DEBUGCTL.LBR before forwarding it.
13719 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13720 */
13721 VMMRZCallRing3Disable(pVCpu);
13722 HM_DISABLE_PREEMPT(pVCpu);
13723
13724 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13725 pCtx->dr[6] |= uDR6;
13726 if (CPUMIsGuestDebugStateActive(pVCpu))
13727 ASMSetDR6(pCtx->dr[6]);
13728
13729 HM_RESTORE_PREEMPT();
13730 VMMRZCallRing3Enable(pVCpu);
13731
13732 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13733 AssertRCReturn(rc, rc);
13734
13735 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13736 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13737
13738 /* Paranoia. */
13739 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13740 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13741
13742 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13743 AssertRC(rc);
13744
13745 /*
13746 * Raise #DB in the guest.
13747 *
13748 * It is important to reflect exactly what the VM-exit gave us (preserving the
13749 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13750 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13751 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13752 *
13753 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13754 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13755 */
13756 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13757 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13758 return VINF_SUCCESS;
13759 }
13760
13761 /*
13762 * Not a guest trap, must be a hypervisor related debug event then.
13763 * Update DR6 in case someone is interested in it.
13764 */
13765 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13766 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13767 CPUMSetHyperDR6(pVCpu, uDR6);
13768
13769 return rc;
13770}
13771
13772
13773/**
13774 * Hacks its way around the lovely mesa driver's backdoor accesses.
13775 *
13776 * @sa hmR0SvmHandleMesaDrvGp.
13777 */
13778static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13779{
13780 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13781 RT_NOREF(pCtx);
13782
13783 /* For now we'll just skip the instruction. */
13784 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13785}
13786
13787
13788/**
13789 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13790 * backdoor logging w/o checking what it is running inside.
13791 *
13792 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13793 * backdoor port and magic numbers loaded in registers.
13794 *
13795 * @returns true if it is, false if it isn't.
13796 * @sa hmR0SvmIsMesaDrvGp.
13797 */
13798DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13799{
13800 /* 0xed: IN eAX,dx */
13801 uint8_t abInstr[1];
13802 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
13803 return false;
13804
13805 /* Check that it is #GP(0). */
13806 if (pVmxTransient->uExitIntErrorCode != 0)
13807 return false;
13808
13809 /* Check magic and port. */
13810 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13811 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13812 if (pCtx->rax != UINT32_C(0x564d5868))
13813 return false;
13814 if (pCtx->dx != UINT32_C(0x5658))
13815 return false;
13816
13817 /* Flat ring-3 CS. */
13818 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13819 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13820 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13821 if (pCtx->cs.Attr.n.u2Dpl != 3)
13822 return false;
13823 if (pCtx->cs.u64Base != 0)
13824 return false;
13825
13826 /* Check opcode. */
13827 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13828 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13829 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13830 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13831 if (RT_FAILURE(rc))
13832 return false;
13833 if (abInstr[0] != 0xed)
13834 return false;
13835
13836 return true;
13837}
13838
13839
13840/**
13841 * VM-exit exception handler for \#GP (General-protection exception).
13842 *
13843 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13844 */
13845static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13846{
13847 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13848 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13849
13850 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13851 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13852 if (pVmcsInfo->RealMode.fRealOnV86Active)
13853 { /* likely */ }
13854 else
13855 {
13856#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13857 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13858#endif
13859 /*
13860 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13861 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13862 */
13863 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13864 AssertRCReturn(rc, rc);
13865 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13866 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13867
13868 if ( pVmxTransient->fIsNestedGuest
13869 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13870 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13871 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13872 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13873 else
13874 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13875 return rc;
13876 }
13877
13878 Assert(CPUMIsGuestInRealModeEx(pCtx));
13879 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13880 Assert(!pVmxTransient->fIsNestedGuest);
13881
13882 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13883 AssertRCReturn(rc, rc);
13884
13885 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13886 if (rcStrict == VINF_SUCCESS)
13887 {
13888 if (!CPUMIsGuestInRealModeEx(pCtx))
13889 {
13890 /*
13891 * The guest is no longer in real-mode, check if we can continue executing the
13892 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13893 */
13894 pVmcsInfo->RealMode.fRealOnV86Active = false;
13895 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13896 {
13897 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13898 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13899 }
13900 else
13901 {
13902 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13903 rcStrict = VINF_EM_RESCHEDULE;
13904 }
13905 }
13906 else
13907 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13908 }
13909 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13910 {
13911 rcStrict = VINF_SUCCESS;
13912 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13913 }
13914 return VBOXSTRICTRC_VAL(rcStrict);
13915}
13916
13917
13918/**
13919 * VM-exit exception handler wrapper for all other exceptions that are not handled
13920 * by a specific handler.
13921 *
13922 * This simply re-injects the exception back into the VM without any special
13923 * processing.
13924 *
13925 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13926 */
13927static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13928{
13929 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13930
13931#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13932 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13933 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13934 ("uVector=%#x u32XcptBitmap=%#X32\n",
13935 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13936 NOREF(pVmcsInfo);
13937#endif
13938
13939 /*
13940 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13941 * would have been handled while checking exits due to event delivery.
13942 */
13943 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13944
13945#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13946 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13947 AssertRCReturn(rc, rc);
13948 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13949#endif
13950
13951#ifdef VBOX_WITH_STATISTICS
13952 switch (uVector)
13953 {
13954 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13955 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13956 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13957 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13958 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13959 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13960 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13961 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13962 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13963 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13964 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13965 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13966 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13967 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13968 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13969 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13970 default:
13971 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13972 break;
13973 }
13974#endif
13975
13976 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13977 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13978 NOREF(uVector);
13979
13980 /* Re-inject the original exception into the guest. */
13981 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13982 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13983 return VINF_SUCCESS;
13984}
13985
13986
13987/**
13988 * VM-exit exception handler for all exceptions (except NMIs!).
13989 *
13990 * @remarks This may be called for both guests and nested-guests. Take care to not
13991 * make assumptions and avoid doing anything that is not relevant when
13992 * executing a nested-guest (e.g., Mesa driver hacks).
13993 */
13994static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13995{
13996 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13997
13998 /*
13999 * If this VM-exit occurred while delivering an event through the guest IDT, take
14000 * action based on the return code and additional hints (e.g. for page-faults)
14001 * that will be updated in the VMX transient structure.
14002 */
14003 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14004 if (rcStrict == VINF_SUCCESS)
14005 {
14006 /*
14007 * If an exception caused a VM-exit due to delivery of an event, the original
14008 * event may have to be re-injected into the guest. We shall reinject it and
14009 * continue guest execution. However, page-fault is a complicated case and
14010 * needs additional processing done in hmR0VmxExitXcptPF().
14011 */
14012 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14013 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14014 if ( !pVCpu->hm.s.Event.fPending
14015 || uVector == X86_XCPT_PF)
14016 {
14017 switch (uVector)
14018 {
14019 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14020 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14021 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14022 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14023 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14024 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14025 default:
14026 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14027 }
14028 }
14029 /* else: inject pending event before resuming guest execution. */
14030 }
14031 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14032 {
14033 Assert(pVCpu->hm.s.Event.fPending);
14034 rcStrict = VINF_SUCCESS;
14035 }
14036
14037 return rcStrict;
14038}
14039/** @} */
14040
14041
14042/** @name VM-exit handlers.
14043 * @{
14044 */
14045/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14046/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14047/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14048
14049/**
14050 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14051 */
14052HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14053{
14054 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14055 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14056 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14057 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14058 return VINF_SUCCESS;
14059 return VINF_EM_RAW_INTERRUPT;
14060}
14061
14062
14063/**
14064 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14065 * VM-exit.
14066 */
14067HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14068{
14069 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14070 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14071
14072 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14073
14074 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14075 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14076 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14077
14078 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14079 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14080 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14081 NOREF(pVmcsInfo);
14082
14083 VBOXSTRICTRC rcStrict;
14084 switch (uExitIntType)
14085 {
14086 /*
14087 * Host physical NMIs:
14088 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14089 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14090 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14091 *
14092 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14093 * See Intel spec. 27.5.5 "Updating Non-Register State".
14094 */
14095 case VMX_EXIT_INT_INFO_TYPE_NMI:
14096 {
14097 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14098 break;
14099 }
14100
14101 /*
14102 * Privileged software exceptions (#DB from ICEBP),
14103 * Software exceptions (#BP and #OF),
14104 * Hardware exceptions:
14105 * Process the required exceptions and resume guest execution if possible.
14106 */
14107 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14108 Assert(uVector == X86_XCPT_DB);
14109 RT_FALL_THRU();
14110 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14111 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14112 RT_FALL_THRU();
14113 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14114 {
14115 NOREF(uVector);
14116 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14117 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14118 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14119 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14120
14121 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14122 break;
14123 }
14124
14125 default:
14126 {
14127 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14128 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14129 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14130 break;
14131 }
14132 }
14133
14134 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14135 return rcStrict;
14136}
14137
14138
14139/**
14140 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14141 */
14142HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14143{
14144 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14145
14146 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14147 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14148 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14149
14150 /* Evaluate and deliver pending events and resume guest execution. */
14151 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14152 return VINF_SUCCESS;
14153}
14154
14155
14156/**
14157 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14158 */
14159HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14160{
14161 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14162
14163 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14164 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14165 {
14166 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14167 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14168 }
14169
14170 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14171
14172 /*
14173 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14174 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14175 */
14176 uint32_t fIntrState;
14177 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14178 AssertRC(rc);
14179 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14180 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14181 {
14182 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14183 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14184
14185 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14186 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14187 AssertRC(rc);
14188 }
14189
14190 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14191 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14192
14193 /* Evaluate and deliver pending events and resume guest execution. */
14194 return VINF_SUCCESS;
14195}
14196
14197
14198/**
14199 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14200 */
14201HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14202{
14203 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14204 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14205}
14206
14207
14208/**
14209 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14210 */
14211HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14212{
14213 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14214 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14215}
14216
14217
14218/**
14219 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14220 */
14221HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14222{
14223 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14224
14225 /*
14226 * Get the state we need and update the exit history entry.
14227 */
14228 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14229 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14230
14231 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14232 AssertRCReturn(rc, rc);
14233
14234 VBOXSTRICTRC rcStrict;
14235 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14236 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14237 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14238 if (!pExitRec)
14239 {
14240 /*
14241 * Regular CPUID instruction execution.
14242 */
14243 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14244 if (rcStrict == VINF_SUCCESS)
14245 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14246 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14247 {
14248 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14249 rcStrict = VINF_SUCCESS;
14250 }
14251 }
14252 else
14253 {
14254 /*
14255 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14256 */
14257 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14258 AssertRCReturn(rc2, rc2);
14259
14260 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14261 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14262
14263 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14264 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14265
14266 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14267 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14268 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14269 }
14270 return rcStrict;
14271}
14272
14273
14274/**
14275 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14276 */
14277HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14278{
14279 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14280
14281 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14282 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14283 AssertRCReturn(rc, rc);
14284
14285 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14286 return VINF_EM_RAW_EMULATE_INSTR;
14287
14288 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14289 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14290}
14291
14292
14293/**
14294 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14295 */
14296HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14297{
14298 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14299
14300 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14301 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14302 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14303 AssertRCReturn(rc, rc);
14304
14305 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14306 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14307 {
14308 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14309 we must reset offsetting on VM-entry. See @bugref{6634}. */
14310 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14311 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14312 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14313 }
14314 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14315 {
14316 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14317 rcStrict = VINF_SUCCESS;
14318 }
14319 return rcStrict;
14320}
14321
14322
14323/**
14324 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14325 */
14326HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14327{
14328 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14329
14330 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14331 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14332 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14333 AssertRCReturn(rc, rc);
14334
14335 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14336 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14337 {
14338 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14339 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14340 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14341 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14342 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14343 }
14344 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14345 {
14346 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14347 rcStrict = VINF_SUCCESS;
14348 }
14349 return rcStrict;
14350}
14351
14352
14353/**
14354 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14355 */
14356HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14357{
14358 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14359
14360 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14361 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14362 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14363 AssertRCReturn(rc, rc);
14364
14365 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14366 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14367 if (RT_LIKELY(rc == VINF_SUCCESS))
14368 {
14369 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14370 Assert(pVmxTransient->cbExitInstr == 2);
14371 }
14372 else
14373 {
14374 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14375 rc = VERR_EM_INTERPRETER;
14376 }
14377 return rc;
14378}
14379
14380
14381/**
14382 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14383 */
14384HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14385{
14386 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14387
14388 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14389 if (EMAreHypercallInstructionsEnabled(pVCpu))
14390 {
14391 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14392 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14393 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14394 AssertRCReturn(rc, rc);
14395
14396 /* Perform the hypercall. */
14397 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14398 if (rcStrict == VINF_SUCCESS)
14399 {
14400 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14401 AssertRCReturn(rc, rc);
14402 }
14403 else
14404 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14405 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14406 || RT_FAILURE(rcStrict));
14407
14408 /* If the hypercall changes anything other than guest's general-purpose registers,
14409 we would need to reload the guest changed bits here before VM-entry. */
14410 }
14411 else
14412 Log4Func(("Hypercalls not enabled\n"));
14413
14414 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14415 if (RT_FAILURE(rcStrict))
14416 {
14417 hmR0VmxSetPendingXcptUD(pVCpu);
14418 rcStrict = VINF_SUCCESS;
14419 }
14420
14421 return rcStrict;
14422}
14423
14424
14425/**
14426 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14427 */
14428HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14429{
14430 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14431 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14432
14433 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14434 hmR0VmxReadExitQualVmcs(pVmxTransient);
14435 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14436 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14437 AssertRCReturn(rc, rc);
14438
14439 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14440
14441 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14442 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14443 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14444 {
14445 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14446 rcStrict = VINF_SUCCESS;
14447 }
14448 else
14449 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14450 VBOXSTRICTRC_VAL(rcStrict)));
14451 return rcStrict;
14452}
14453
14454
14455/**
14456 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14457 */
14458HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14459{
14460 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14461
14462 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14463 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14464 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14465 AssertRCReturn(rc, rc);
14466
14467 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14468 if (rcStrict == VINF_SUCCESS)
14469 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14470 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14471 {
14472 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14473 rcStrict = VINF_SUCCESS;
14474 }
14475
14476 return rcStrict;
14477}
14478
14479
14480/**
14481 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14482 */
14483HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14484{
14485 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14486
14487 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14488 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14489 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14490 AssertRCReturn(rc, rc);
14491
14492 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14493 if (RT_SUCCESS(rcStrict))
14494 {
14495 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14496 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14497 rcStrict = VINF_SUCCESS;
14498 }
14499
14500 return rcStrict;
14501}
14502
14503
14504/**
14505 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14506 * VM-exit.
14507 */
14508HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14509{
14510 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14511 return VINF_EM_RESET;
14512}
14513
14514
14515/**
14516 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14517 */
14518HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14519{
14520 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14521
14522 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14523 AssertRCReturn(rc, rc);
14524
14525 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14526 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14527 rc = VINF_SUCCESS;
14528 else
14529 rc = VINF_EM_HALT;
14530
14531 if (rc != VINF_SUCCESS)
14532 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14533 return rc;
14534}
14535
14536
14537/**
14538 * VM-exit handler for instructions that result in a \#UD exception delivered to
14539 * the guest.
14540 */
14541HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14542{
14543 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14544 hmR0VmxSetPendingXcptUD(pVCpu);
14545 return VINF_SUCCESS;
14546}
14547
14548
14549/**
14550 * VM-exit handler for expiry of the VMX-preemption timer.
14551 */
14552HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14553{
14554 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14555
14556 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14557 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14558
14559 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14560 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14561 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14562 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14563 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14564}
14565
14566
14567/**
14568 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14569 */
14570HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14571{
14572 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14573
14574 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14575 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14576 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14577 AssertRCReturn(rc, rc);
14578
14579 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14580 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14581 : HM_CHANGED_RAISED_XCPT_MASK);
14582
14583 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14584 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14585
14586 return rcStrict;
14587}
14588
14589
14590/**
14591 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14592 */
14593HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14594{
14595 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14596
14597#if 1
14598 /** @todo Use VM-exit instruction information. */
14599 return VERR_EM_INTERPRETER;
14600#else
14601 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14602 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14603 hmR0VmxReadExitQualVmcs(pVmxTransient);
14604 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14605 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14606 AssertRCReturn(rc, rc);
14607
14608 /* Paranoia. Ensure this has a memory operand. */
14609 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14610
14611 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14612 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14613 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14614 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14615
14616 RTGCPTR GCPtrDesc;
14617 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14618
14619 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14620 GCPtrDesc, uType);
14621 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14622 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14623 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14624 {
14625 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14626 rcStrict = VINF_SUCCESS;
14627 }
14628 return rcStrict;
14629#endif
14630}
14631
14632
14633/**
14634 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14635 * VM-exit.
14636 */
14637HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14638{
14639 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14640 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14641 AssertRCReturn(rc, rc);
14642
14643 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14644 if (RT_FAILURE(rc))
14645 return rc;
14646
14647 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14648 NOREF(uInvalidReason);
14649
14650#ifdef VBOX_STRICT
14651 uint32_t fIntrState;
14652 uint64_t u64Val;
14653 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14654 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14655 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14656
14657 Log4(("uInvalidReason %u\n", uInvalidReason));
14658 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14659 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14660 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14661
14662 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14663 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14664 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14665 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14666 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14667 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14668 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14669 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14670 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14671 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14672 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14673 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14674 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14675 {
14676 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14677 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14678 }
14679 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14680#endif
14681
14682 return VERR_VMX_INVALID_GUEST_STATE;
14683}
14684
14685/**
14686 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14687 */
14688HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14689{
14690 /*
14691 * Cumulative notes of all recognized but unexpected VM-exits.
14692 *
14693 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14694 * nested-paging is used.
14695 *
14696 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14697 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14698 * this function (and thereby stop VM execution) for handling such instructions.
14699 *
14700 *
14701 * VMX_EXIT_INIT_SIGNAL:
14702 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14703 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14704 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14705 *
14706 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14707 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14708 * See Intel spec. "23.8 Restrictions on VMX operation".
14709 *
14710 * VMX_EXIT_SIPI:
14711 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14712 * activity state is used. We don't make use of it as our guests don't have direct
14713 * access to the host local APIC.
14714 *
14715 * See Intel spec. 25.3 "Other Causes of VM-exits".
14716 *
14717 * VMX_EXIT_IO_SMI:
14718 * VMX_EXIT_SMI:
14719 * This can only happen if we support dual-monitor treatment of SMI, which can be
14720 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14721 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14722 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14723 *
14724 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14725 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14726 *
14727 * VMX_EXIT_ERR_MSR_LOAD:
14728 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14729 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14730 * execution.
14731 *
14732 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14733 *
14734 * VMX_EXIT_ERR_MACHINE_CHECK:
14735 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14736 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14737 * #MC exception abort class exception is raised. We thus cannot assume a
14738 * reasonable chance of continuing any sort of execution and we bail.
14739 *
14740 * See Intel spec. 15.1 "Machine-check Architecture".
14741 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14742 *
14743 * VMX_EXIT_PML_FULL:
14744 * VMX_EXIT_VIRTUALIZED_EOI:
14745 * VMX_EXIT_APIC_WRITE:
14746 * We do not currently support any of these features and thus they are all unexpected
14747 * VM-exits.
14748 *
14749 * VMX_EXIT_GDTR_IDTR_ACCESS:
14750 * VMX_EXIT_LDTR_TR_ACCESS:
14751 * VMX_EXIT_RDRAND:
14752 * VMX_EXIT_RSM:
14753 * VMX_EXIT_VMFUNC:
14754 * VMX_EXIT_ENCLS:
14755 * VMX_EXIT_RDSEED:
14756 * VMX_EXIT_XSAVES:
14757 * VMX_EXIT_XRSTORS:
14758 * VMX_EXIT_UMWAIT:
14759 * VMX_EXIT_TPAUSE:
14760 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14761 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14762 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14763 *
14764 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14765 */
14766 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14767 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14768 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14769}
14770
14771
14772/**
14773 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14774 */
14775HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14776{
14777 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14778
14779 /** @todo Optimize this: We currently drag in the whole MSR state
14780 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14781 * MSRs required. That would require changes to IEM and possibly CPUM too.
14782 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14783 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14784 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14785 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14786 switch (idMsr)
14787 {
14788 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14789 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14790 }
14791
14792 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14793 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14794 AssertRCReturn(rc, rc);
14795
14796 Log4Func(("ecx=%#RX32\n", idMsr));
14797
14798#ifdef VBOX_STRICT
14799 Assert(!pVmxTransient->fIsNestedGuest);
14800 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14801 {
14802 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14803 && idMsr != MSR_K6_EFER)
14804 {
14805 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14806 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14807 }
14808 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14809 {
14810 Assert(pVmcsInfo->pvMsrBitmap);
14811 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14812 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14813 {
14814 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14815 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14816 }
14817 }
14818 }
14819#endif
14820
14821 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
14822 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14823 if (rcStrict == VINF_SUCCESS)
14824 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14825 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
14826 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14827 {
14828 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14829 rcStrict = VINF_SUCCESS;
14830 }
14831 else
14832 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14833
14834 return rcStrict;
14835}
14836
14837
14838/**
14839 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14840 */
14841HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14842{
14843 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14844
14845 /** @todo Optimize this: We currently drag in the whole MSR state
14846 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14847 * MSRs required. That would require changes to IEM and possibly CPUM too.
14848 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14849 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14850 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14851
14852 /*
14853 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14854 * Although we don't need to fetch the base as it will be overwritten shortly, while
14855 * loading guest-state we would also load the entire segment register including limit
14856 * and attributes and thus we need to load them here.
14857 */
14858 switch (idMsr)
14859 {
14860 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14861 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14862 }
14863
14864 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14865 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14866 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14867 AssertRCReturn(rc, rc);
14868
14869 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14870
14871 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
14872 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14873
14874 if (rcStrict == VINF_SUCCESS)
14875 {
14876 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14877
14878 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14879 if ( idMsr == MSR_IA32_APICBASE
14880 || ( idMsr >= MSR_IA32_X2APIC_START
14881 && idMsr <= MSR_IA32_X2APIC_END))
14882 {
14883 /*
14884 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14885 * When full APIC register virtualization is implemented we'll have to make
14886 * sure APIC state is saved from the VMCS before IEM changes it.
14887 */
14888 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14889 }
14890 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14891 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14892 else if (idMsr == MSR_K6_EFER)
14893 {
14894 /*
14895 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14896 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14897 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14898 */
14899 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14900 }
14901
14902 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14903 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14904 {
14905 switch (idMsr)
14906 {
14907 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14908 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14909 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14910 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14911 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14912 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14913 default:
14914 {
14915 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14916 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14917 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14918 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14919 break;
14920 }
14921 }
14922 }
14923#ifdef VBOX_STRICT
14924 else
14925 {
14926 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14927 switch (idMsr)
14928 {
14929 case MSR_IA32_SYSENTER_CS:
14930 case MSR_IA32_SYSENTER_EIP:
14931 case MSR_IA32_SYSENTER_ESP:
14932 case MSR_K8_FS_BASE:
14933 case MSR_K8_GS_BASE:
14934 {
14935 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14936 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14937 }
14938
14939 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14940 default:
14941 {
14942 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14943 {
14944 /* EFER MSR writes are always intercepted. */
14945 if (idMsr != MSR_K6_EFER)
14946 {
14947 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14948 idMsr));
14949 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14950 }
14951 }
14952
14953 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14954 {
14955 Assert(pVmcsInfo->pvMsrBitmap);
14956 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14957 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14958 {
14959 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14960 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14961 }
14962 }
14963 break;
14964 }
14965 }
14966 }
14967#endif /* VBOX_STRICT */
14968 }
14969 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14970 {
14971 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14972 rcStrict = VINF_SUCCESS;
14973 }
14974 else
14975 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14976
14977 return rcStrict;
14978}
14979
14980
14981/**
14982 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14983 */
14984HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14985{
14986 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14987
14988 /** @todo The guest has likely hit a contended spinlock. We might want to
14989 * poke a schedule different guest VCPU. */
14990 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14991 if (RT_SUCCESS(rc))
14992 return VINF_EM_RAW_INTERRUPT;
14993
14994 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
14995 return rc;
14996}
14997
14998
14999/**
15000 * VM-exit handler for when the TPR value is lowered below the specified
15001 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15002 */
15003HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15004{
15005 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15006 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15007
15008 /*
15009 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15010 * We'll re-evaluate pending interrupts and inject them before the next VM
15011 * entry so we can just continue execution here.
15012 */
15013 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15014 return VINF_SUCCESS;
15015}
15016
15017
15018/**
15019 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15020 * VM-exit.
15021 *
15022 * @retval VINF_SUCCESS when guest execution can continue.
15023 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15024 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15025 * incompatible guest state for VMX execution (real-on-v86 case).
15026 */
15027HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15028{
15029 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15030 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15031
15032 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15033 hmR0VmxReadExitQualVmcs(pVmxTransient);
15034 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15035
15036 VBOXSTRICTRC rcStrict;
15037 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15038 uint64_t const uExitQual = pVmxTransient->uExitQual;
15039 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15040 switch (uAccessType)
15041 {
15042 /*
15043 * MOV to CRx.
15044 */
15045 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15046 {
15047 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15048 AssertRCReturn(rc, rc);
15049
15050 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15051 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15052 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15053 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15054
15055 /*
15056 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15057 * - When nested paging isn't used.
15058 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15059 * - We are executing in the VM debug loop.
15060 */
15061 Assert( iCrReg != 3
15062 || !pVM->hm.s.fNestedPaging
15063 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15064 || pVCpu->hm.s.fUsingDebugLoop);
15065
15066 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15067 Assert( iCrReg != 8
15068 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15069
15070 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15071 AssertMsg( rcStrict == VINF_SUCCESS
15072 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15073
15074 /*
15075 * This is a kludge for handling switches back to real mode when we try to use
15076 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15077 * deal with special selector values, so we have to return to ring-3 and run
15078 * there till the selector values are V86 mode compatible.
15079 *
15080 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15081 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15082 * this function.
15083 */
15084 if ( iCrReg == 0
15085 && rcStrict == VINF_SUCCESS
15086 && !pVM->hm.s.vmx.fUnrestrictedGuest
15087 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15088 && (uOldCr0 & X86_CR0_PE)
15089 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15090 {
15091 /** @todo Check selectors rather than returning all the time. */
15092 Assert(!pVmxTransient->fIsNestedGuest);
15093 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15094 rcStrict = VINF_EM_RESCHEDULE_REM;
15095 }
15096 break;
15097 }
15098
15099 /*
15100 * MOV from CRx.
15101 */
15102 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15103 {
15104 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15105 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15106
15107 /*
15108 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15109 * - When nested paging isn't used.
15110 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15111 * - We are executing in the VM debug loop.
15112 */
15113 Assert( iCrReg != 3
15114 || !pVM->hm.s.fNestedPaging
15115 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15116 || pVCpu->hm.s.fUsingDebugLoop);
15117
15118 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15119 Assert( iCrReg != 8
15120 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15121
15122 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15123 break;
15124 }
15125
15126 /*
15127 * CLTS (Clear Task-Switch Flag in CR0).
15128 */
15129 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15130 {
15131 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15132 break;
15133 }
15134
15135 /*
15136 * LMSW (Load Machine-Status Word into CR0).
15137 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15138 */
15139 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15140 {
15141 RTGCPTR GCPtrEffDst;
15142 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15143 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15144 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15145 if (fMemOperand)
15146 {
15147 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15148 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15149 }
15150 else
15151 GCPtrEffDst = NIL_RTGCPTR;
15152 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15153 break;
15154 }
15155
15156 default:
15157 {
15158 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15159 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15160 }
15161 }
15162
15163 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15164 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15165 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15166
15167 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15168 NOREF(pVM);
15169 return rcStrict;
15170}
15171
15172
15173/**
15174 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15175 * VM-exit.
15176 */
15177HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15178{
15179 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15180 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15181
15182 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15183 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15184 hmR0VmxReadExitQualVmcs(pVmxTransient);
15185 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15186 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15187 | CPUMCTX_EXTRN_EFER);
15188 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15189 AssertRCReturn(rc, rc);
15190
15191 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15192 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15193 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15194 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15195 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15196 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15197 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15198 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15199
15200 /*
15201 * Update exit history to see if this exit can be optimized.
15202 */
15203 VBOXSTRICTRC rcStrict;
15204 PCEMEXITREC pExitRec = NULL;
15205 if ( !fGstStepping
15206 && !fDbgStepping)
15207 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15208 !fIOString
15209 ? !fIOWrite
15210 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15211 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15212 : !fIOWrite
15213 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15214 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15215 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15216 if (!pExitRec)
15217 {
15218 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15219 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15220
15221 uint32_t const cbValue = s_aIOSizes[uIOSize];
15222 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15223 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15224 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15225 if (fIOString)
15226 {
15227 /*
15228 * INS/OUTS - I/O String instruction.
15229 *
15230 * Use instruction-information if available, otherwise fall back on
15231 * interpreting the instruction.
15232 */
15233 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15234 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15235 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15236 if (fInsOutsInfo)
15237 {
15238 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15239 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15240 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15241 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15242 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15243 if (fIOWrite)
15244 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15245 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15246 else
15247 {
15248 /*
15249 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15250 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15251 * See Intel Instruction spec. for "INS".
15252 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15253 */
15254 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15255 }
15256 }
15257 else
15258 rcStrict = IEMExecOne(pVCpu);
15259
15260 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15261 fUpdateRipAlready = true;
15262 }
15263 else
15264 {
15265 /*
15266 * IN/OUT - I/O instruction.
15267 */
15268 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15269 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15270 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15271 if (fIOWrite)
15272 {
15273 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15274 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15275 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15276 && !pCtx->eflags.Bits.u1TF)
15277 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15278 }
15279 else
15280 {
15281 uint32_t u32Result = 0;
15282 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15283 if (IOM_SUCCESS(rcStrict))
15284 {
15285 /* Save result of I/O IN instr. in AL/AX/EAX. */
15286 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15287 }
15288 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15289 && !pCtx->eflags.Bits.u1TF)
15290 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15291 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15292 }
15293 }
15294
15295 if (IOM_SUCCESS(rcStrict))
15296 {
15297 if (!fUpdateRipAlready)
15298 {
15299 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15300 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15301 }
15302
15303 /*
15304 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15305 * while booting Fedora 17 64-bit guest.
15306 *
15307 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15308 */
15309 if (fIOString)
15310 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15311
15312 /*
15313 * If any I/O breakpoints are armed, we need to check if one triggered
15314 * and take appropriate action.
15315 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15316 */
15317 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15318 AssertRCReturn(rc, rc);
15319
15320 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15321 * execution engines about whether hyper BPs and such are pending. */
15322 uint32_t const uDr7 = pCtx->dr[7];
15323 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15324 && X86_DR7_ANY_RW_IO(uDr7)
15325 && (pCtx->cr4 & X86_CR4_DE))
15326 || DBGFBpIsHwIoArmed(pVM)))
15327 {
15328 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15329
15330 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15331 VMMRZCallRing3Disable(pVCpu);
15332 HM_DISABLE_PREEMPT(pVCpu);
15333
15334 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15335
15336 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15337 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15338 {
15339 /* Raise #DB. */
15340 if (fIsGuestDbgActive)
15341 ASMSetDR6(pCtx->dr[6]);
15342 if (pCtx->dr[7] != uDr7)
15343 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15344
15345 hmR0VmxSetPendingXcptDB(pVCpu);
15346 }
15347 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15348 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15349 else if ( rcStrict2 != VINF_SUCCESS
15350 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15351 rcStrict = rcStrict2;
15352 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15353
15354 HM_RESTORE_PREEMPT();
15355 VMMRZCallRing3Enable(pVCpu);
15356 }
15357 }
15358
15359#ifdef VBOX_STRICT
15360 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15361 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15362 Assert(!fIOWrite);
15363 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15364 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15365 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15366 Assert(fIOWrite);
15367 else
15368 {
15369# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15370 * statuses, that the VMM device and some others may return. See
15371 * IOM_SUCCESS() for guidance. */
15372 AssertMsg( RT_FAILURE(rcStrict)
15373 || rcStrict == VINF_SUCCESS
15374 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15375 || rcStrict == VINF_EM_DBG_BREAKPOINT
15376 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15377 || rcStrict == VINF_EM_RAW_TO_R3
15378 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15379# endif
15380 }
15381#endif
15382 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15383 }
15384 else
15385 {
15386 /*
15387 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15388 */
15389 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15390 AssertRCReturn(rc2, rc2);
15391 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15392 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15393 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15394 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15395 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15396 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15397
15398 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15399 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15400
15401 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15402 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15403 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15404 }
15405 return rcStrict;
15406}
15407
15408
15409/**
15410 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15411 * VM-exit.
15412 */
15413HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15414{
15415 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15416
15417 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15418 hmR0VmxReadExitQualVmcs(pVmxTransient);
15419 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15420 {
15421 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15422 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15423 {
15424 uint32_t uErrCode;
15425 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15426 {
15427 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15428 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15429 }
15430 else
15431 uErrCode = 0;
15432
15433 RTGCUINTPTR GCPtrFaultAddress;
15434 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15435 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15436 else
15437 GCPtrFaultAddress = 0;
15438
15439 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15440
15441 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15442 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15443
15444 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15445 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15446 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15447 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15448 }
15449 }
15450
15451 /* Fall back to the interpreter to emulate the task-switch. */
15452 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15453 return VERR_EM_INTERPRETER;
15454}
15455
15456
15457/**
15458 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15459 */
15460HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15461{
15462 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15463
15464 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15465 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15466 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15467 AssertRC(rc);
15468 return VINF_EM_DBG_STEPPED;
15469}
15470
15471
15472/**
15473 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15474 */
15475HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15476{
15477 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15478 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15479
15480 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15481 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15482 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15483 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15484 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15485
15486 /*
15487 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15488 */
15489 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15490 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15491 {
15492 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15493 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15494 {
15495 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15496 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15497 }
15498 }
15499 else
15500 {
15501 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15502 return rcStrict;
15503 }
15504
15505 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15506 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15507 hmR0VmxReadExitQualVmcs(pVmxTransient);
15508 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15509 AssertRCReturn(rc, rc);
15510
15511 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15512 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15513 switch (uAccessType)
15514 {
15515 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15516 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15517 {
15518 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15519 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15520 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15521
15522 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15523 GCPhys &= PAGE_BASE_GC_MASK;
15524 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15525 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15526 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15527
15528 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15529 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15530 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
15531 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
15532 CPUMCTX2CORE(pCtx), GCPhys);
15533 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15534 if ( rcStrict == VINF_SUCCESS
15535 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15536 || rcStrict == VERR_PAGE_NOT_PRESENT)
15537 {
15538 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15539 | HM_CHANGED_GUEST_APIC_TPR);
15540 rcStrict = VINF_SUCCESS;
15541 }
15542 break;
15543 }
15544
15545 default:
15546 {
15547 Log4Func(("uAccessType=%#x\n", uAccessType));
15548 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15549 break;
15550 }
15551 }
15552
15553 if (rcStrict != VINF_SUCCESS)
15554 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15555 return rcStrict;
15556}
15557
15558
15559/**
15560 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15561 * VM-exit.
15562 */
15563HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15564{
15565 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15566 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15567
15568 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15569 if (!pVmxTransient->fIsNestedGuest)
15570 {
15571 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15572 if (pVmxTransient->fWasGuestDebugStateActive)
15573 {
15574 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15575 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15576 }
15577
15578 if ( !pVCpu->hm.s.fSingleInstruction
15579 && !pVmxTransient->fWasHyperDebugStateActive)
15580 {
15581 Assert(!DBGFIsStepping(pVCpu));
15582 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15583
15584 /* Don't intercept MOV DRx any more. */
15585 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15586 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15587 AssertRC(rc);
15588
15589 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15590 VMMRZCallRing3Disable(pVCpu);
15591 HM_DISABLE_PREEMPT(pVCpu);
15592
15593 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15594 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15595 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15596
15597 HM_RESTORE_PREEMPT();
15598 VMMRZCallRing3Enable(pVCpu);
15599
15600#ifdef VBOX_WITH_STATISTICS
15601 hmR0VmxReadExitQualVmcs(pVmxTransient);
15602 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15603 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15604 else
15605 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15606#endif
15607 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15608 return VINF_SUCCESS;
15609 }
15610 }
15611
15612 /*
15613 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15614 * The EFER MSR is always up-to-date.
15615 * Update the segment registers and DR7 from the CPU.
15616 */
15617 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15618 hmR0VmxReadExitQualVmcs(pVmxTransient);
15619 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15620 AssertRCReturn(rc, rc);
15621 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15622
15623 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15624 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15625 {
15626 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15627 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15628 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15629 if (RT_SUCCESS(rc))
15630 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15631 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15632 }
15633 else
15634 {
15635 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15636 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15637 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15638 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15639 }
15640
15641 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15642 if (RT_SUCCESS(rc))
15643 {
15644 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15645 AssertRCReturn(rc2, rc2);
15646 return VINF_SUCCESS;
15647 }
15648 return rc;
15649}
15650
15651
15652/**
15653 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15654 * Conditional VM-exit.
15655 */
15656HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15657{
15658 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15659 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15660
15661 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15662 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15663 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15664 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15665 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15666
15667 /*
15668 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15669 */
15670 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15671 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15672 {
15673 /*
15674 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15675 * instruction emulation to inject the original event. Otherwise, injecting the original event
15676 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15677 */
15678 if (!pVCpu->hm.s.Event.fPending)
15679 { /* likely */ }
15680 else
15681 {
15682 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15683#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15684 /** @todo NSTVMX: Think about how this should be handled. */
15685 if (pVmxTransient->fIsNestedGuest)
15686 return VERR_VMX_IPE_3;
15687#endif
15688 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15689 }
15690 }
15691 else
15692 {
15693 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15694 return rcStrict;
15695 }
15696
15697 /*
15698 * Get sufficient state and update the exit history entry.
15699 */
15700 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15701 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15702 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15703 AssertRCReturn(rc, rc);
15704
15705 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15706 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15707 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15708 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15709 if (!pExitRec)
15710 {
15711 /*
15712 * If we succeed, resume guest execution.
15713 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15714 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15715 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15716 * weird case. See @bugref{6043}.
15717 */
15718 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15719 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15720 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15721 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15722 if ( rcStrict == VINF_SUCCESS
15723 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15724 || rcStrict == VERR_PAGE_NOT_PRESENT)
15725 {
15726 /* Successfully handled MMIO operation. */
15727 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15728 | HM_CHANGED_GUEST_APIC_TPR);
15729 rcStrict = VINF_SUCCESS;
15730 }
15731 }
15732 else
15733 {
15734 /*
15735 * Frequent exit or something needing probing. Call EMHistoryExec.
15736 */
15737 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15738 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15739
15740 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15741 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15742
15743 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15744 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15745 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15746 }
15747 return rcStrict;
15748}
15749
15750
15751/**
15752 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15753 * VM-exit.
15754 */
15755HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15756{
15757 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15758 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15759
15760 hmR0VmxReadExitQualVmcs(pVmxTransient);
15761 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15762 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15763 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15764 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15765 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15766
15767 /*
15768 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15769 */
15770 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15771 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15772 {
15773 /*
15774 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15775 * we shall resolve the nested #PF and re-inject the original event.
15776 */
15777 if (pVCpu->hm.s.Event.fPending)
15778 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15779 }
15780 else
15781 {
15782 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15783 return rcStrict;
15784 }
15785
15786 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15787 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15788 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15789 AssertRCReturn(rc, rc);
15790
15791 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15792 uint64_t const uExitQual = pVmxTransient->uExitQual;
15793 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15794
15795 RTGCUINT uErrorCode = 0;
15796 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15797 uErrorCode |= X86_TRAP_PF_ID;
15798 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15799 uErrorCode |= X86_TRAP_PF_RW;
15800 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15801 uErrorCode |= X86_TRAP_PF_P;
15802
15803 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15804 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15805 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15806
15807 /*
15808 * Handle the pagefault trap for the nested shadow table.
15809 */
15810 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15811 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15812 TRPMResetTrap(pVCpu);
15813
15814 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15815 if ( rcStrict == VINF_SUCCESS
15816 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15817 || rcStrict == VERR_PAGE_NOT_PRESENT)
15818 {
15819 /* Successfully synced our nested page tables. */
15820 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15821 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15822 return VINF_SUCCESS;
15823 }
15824
15825 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15826 return rcStrict;
15827}
15828
15829
15830#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15831/**
15832 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15833 */
15834HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15835{
15836 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15837
15838 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15839 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15840 hmR0VmxReadExitQualVmcs(pVmxTransient);
15841 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15842 | CPUMCTX_EXTRN_HWVIRT
15843 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15844 AssertRCReturn(rc, rc);
15845
15846 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15847
15848 VMXVEXITINFO ExitInfo;
15849 RT_ZERO(ExitInfo);
15850 ExitInfo.uReason = pVmxTransient->uExitReason;
15851 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15852 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15853 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15854 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15855
15856 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15857 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15858 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15859 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15860 {
15861 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15862 rcStrict = VINF_SUCCESS;
15863 }
15864 return rcStrict;
15865}
15866
15867
15868/**
15869 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15870 */
15871HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15872{
15873 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15874
15875 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15876 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15877 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15878 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15879 AssertRCReturn(rc, rc);
15880
15881 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15882
15883 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15884 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
15885 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15886 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15887 {
15888 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15889 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15890 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15891 }
15892 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15893 return rcStrict;
15894}
15895
15896
15897/**
15898 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15899 */
15900HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15901{
15902 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15903
15904 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15905 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15906 hmR0VmxReadExitQualVmcs(pVmxTransient);
15907 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15908 | CPUMCTX_EXTRN_HWVIRT
15909 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15910 AssertRCReturn(rc, rc);
15911
15912 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15913
15914 VMXVEXITINFO ExitInfo;
15915 RT_ZERO(ExitInfo);
15916 ExitInfo.uReason = pVmxTransient->uExitReason;
15917 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15918 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15919 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15920 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15921
15922 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15923 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15924 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15925 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15926 {
15927 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15928 rcStrict = VINF_SUCCESS;
15929 }
15930 return rcStrict;
15931}
15932
15933
15934/**
15935 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15936 */
15937HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15938{
15939 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15940
15941 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15942 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15943 hmR0VmxReadExitQualVmcs(pVmxTransient);
15944 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15945 | CPUMCTX_EXTRN_HWVIRT
15946 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15947 AssertRCReturn(rc, rc);
15948
15949 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15950
15951 VMXVEXITINFO ExitInfo;
15952 RT_ZERO(ExitInfo);
15953 ExitInfo.uReason = pVmxTransient->uExitReason;
15954 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15955 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15956 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15957 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15958
15959 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15960 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15961 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15962 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15963 {
15964 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15965 rcStrict = VINF_SUCCESS;
15966 }
15967 return rcStrict;
15968}
15969
15970
15971/**
15972 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15973 */
15974HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15975{
15976 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15977
15978 /*
15979 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15980 * thus might not need to import the shadow VMCS state, it's safer just in case
15981 * code elsewhere dares look at unsynced VMCS fields.
15982 */
15983 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15984 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15985 hmR0VmxReadExitQualVmcs(pVmxTransient);
15986 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15987 | CPUMCTX_EXTRN_HWVIRT
15988 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15989 AssertRCReturn(rc, rc);
15990
15991 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15992
15993 VMXVEXITINFO ExitInfo;
15994 RT_ZERO(ExitInfo);
15995 ExitInfo.uReason = pVmxTransient->uExitReason;
15996 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15997 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15998 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15999 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16000 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16001
16002 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16003 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16004 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16005 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16006 {
16007 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16008 rcStrict = VINF_SUCCESS;
16009 }
16010 return rcStrict;
16011}
16012
16013
16014/**
16015 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16016 */
16017HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16018{
16019 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16020
16021 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16022 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16023 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16024 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16025 AssertRCReturn(rc, rc);
16026
16027 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16028
16029 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16030 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
16031 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16032 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16033 {
16034 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16035 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16036 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16037 }
16038 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16039 return rcStrict;
16040}
16041
16042
16043/**
16044 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16045 */
16046HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16047{
16048 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16049
16050 /*
16051 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16052 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16053 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16054 */
16055 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16056 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16057 hmR0VmxReadExitQualVmcs(pVmxTransient);
16058 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16059 | CPUMCTX_EXTRN_HWVIRT
16060 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16061 AssertRCReturn(rc, rc);
16062
16063 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16064
16065 VMXVEXITINFO ExitInfo;
16066 RT_ZERO(ExitInfo);
16067 ExitInfo.uReason = pVmxTransient->uExitReason;
16068 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16069 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16070 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16071 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16072 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16073
16074 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16075 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16076 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16077 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16078 {
16079 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16080 rcStrict = VINF_SUCCESS;
16081 }
16082 return rcStrict;
16083}
16084
16085
16086/**
16087 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16088 */
16089HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16090{
16091 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16092
16093 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16094 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16095 | CPUMCTX_EXTRN_HWVIRT
16096 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16097 AssertRCReturn(rc, rc);
16098
16099 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16100
16101 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16102 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16103 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16104 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16105 {
16106 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16107 rcStrict = VINF_SUCCESS;
16108 }
16109 return rcStrict;
16110}
16111
16112
16113/**
16114 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16115 */
16116HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16117{
16118 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16119
16120 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16121 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16122 hmR0VmxReadExitQualVmcs(pVmxTransient);
16123 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16124 | CPUMCTX_EXTRN_HWVIRT
16125 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16126 AssertRCReturn(rc, rc);
16127
16128 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16129
16130 VMXVEXITINFO ExitInfo;
16131 RT_ZERO(ExitInfo);
16132 ExitInfo.uReason = pVmxTransient->uExitReason;
16133 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16134 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16135 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16136 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16137
16138 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16139 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16140 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16141 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16142 {
16143 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16144 rcStrict = VINF_SUCCESS;
16145 }
16146 return rcStrict;
16147}
16148
16149
16150/**
16151 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16152 */
16153HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16154{
16155 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16156
16157 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16158 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16159 hmR0VmxReadExitQualVmcs(pVmxTransient);
16160 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16161 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16162 AssertRCReturn(rc, rc);
16163
16164 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16165
16166 VMXVEXITINFO ExitInfo;
16167 RT_ZERO(ExitInfo);
16168 ExitInfo.uReason = pVmxTransient->uExitReason;
16169 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16170 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16171 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16172 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16173
16174 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16175 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16176 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16177 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16178 {
16179 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16180 rcStrict = VINF_SUCCESS;
16181 }
16182 return rcStrict;
16183}
16184#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16185/** @} */
16186
16187
16188#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16189/** @name Nested-guest VM-exit handlers.
16190 * @{
16191 */
16192/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16193/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16194/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16195
16196/**
16197 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16198 * Conditional VM-exit.
16199 */
16200HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16201{
16202 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16203
16204 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16205
16206 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16207 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16208 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16209
16210 switch (uExitIntType)
16211 {
16212 /*
16213 * Physical NMIs:
16214 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16215 */
16216 case VMX_EXIT_INT_INFO_TYPE_NMI:
16217 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16218
16219 /*
16220 * Hardware exceptions,
16221 * Software exceptions,
16222 * Privileged software exceptions:
16223 * Figure out if the exception must be delivered to the guest or the nested-guest.
16224 */
16225 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16226 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16227 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16228 {
16229 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16230 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16231 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16232 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16233
16234 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16235 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16236 pVmxTransient->uExitIntErrorCode);
16237 if (fIntercept)
16238 {
16239 /* Exit qualification is required for debug and page-fault exceptions. */
16240 hmR0VmxReadExitQualVmcs(pVmxTransient);
16241
16242 /*
16243 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16244 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16245 * length. However, if delivery of a software interrupt, software exception or privileged
16246 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16247 */
16248 VMXVEXITINFO ExitInfo;
16249 RT_ZERO(ExitInfo);
16250 ExitInfo.uReason = pVmxTransient->uExitReason;
16251 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16252 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16253
16254 VMXVEXITEVENTINFO ExitEventInfo;
16255 RT_ZERO(ExitEventInfo);
16256 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16257 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16258 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16259 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16260
16261#ifdef DEBUG_ramshankar
16262 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16263 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16264 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16265 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16266 {
16267 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16268 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16269 }
16270#endif
16271 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16272 }
16273
16274 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16275 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16276 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16277 }
16278
16279 /*
16280 * Software interrupts:
16281 * VM-exits cannot be caused by software interrupts.
16282 *
16283 * External interrupts:
16284 * This should only happen when "acknowledge external interrupts on VM-exit"
16285 * control is set. However, we never set this when executing a guest or
16286 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16287 * the guest.
16288 */
16289 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16290 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16291 default:
16292 {
16293 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16294 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16295 }
16296 }
16297}
16298
16299
16300/**
16301 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16302 * Unconditional VM-exit.
16303 */
16304HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16305{
16306 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16307 return IEMExecVmxVmexitTripleFault(pVCpu);
16308}
16309
16310
16311/**
16312 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16313 */
16314HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16315{
16316 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16317
16318 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16319 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16320 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16321}
16322
16323
16324/**
16325 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16326 */
16327HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16328{
16329 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16330
16331 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16332 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16333 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16334}
16335
16336
16337/**
16338 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16339 * Unconditional VM-exit.
16340 */
16341HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16342{
16343 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16344
16345 hmR0VmxReadExitQualVmcs(pVmxTransient);
16346 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16347 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16348 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16349
16350 VMXVEXITINFO ExitInfo;
16351 RT_ZERO(ExitInfo);
16352 ExitInfo.uReason = pVmxTransient->uExitReason;
16353 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16354 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16355
16356 VMXVEXITEVENTINFO ExitEventInfo;
16357 RT_ZERO(ExitEventInfo);
16358 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16359 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16360 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16361}
16362
16363
16364/**
16365 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16366 */
16367HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16368{
16369 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16370
16371 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16372 {
16373 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16374 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16375 }
16376 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16377}
16378
16379
16380/**
16381 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16382 */
16383HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16384{
16385 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16386
16387 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16388 {
16389 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16390 hmR0VmxReadExitQualVmcs(pVmxTransient);
16391
16392 VMXVEXITINFO ExitInfo;
16393 RT_ZERO(ExitInfo);
16394 ExitInfo.uReason = pVmxTransient->uExitReason;
16395 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16396 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16397 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16398 }
16399 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16400}
16401
16402
16403/**
16404 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16405 */
16406HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16407{
16408 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16409
16410 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16411 {
16412 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16413 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16414 }
16415 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16416}
16417
16418
16419/**
16420 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16421 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16422 */
16423HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16424{
16425 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16426
16427 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16428 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16429
16430 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16431
16432 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16433 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16434 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16435
16436 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16437 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16438 u64VmcsField &= UINT64_C(0xffffffff);
16439
16440 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16441 {
16442 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16443 hmR0VmxReadExitQualVmcs(pVmxTransient);
16444
16445 VMXVEXITINFO ExitInfo;
16446 RT_ZERO(ExitInfo);
16447 ExitInfo.uReason = pVmxTransient->uExitReason;
16448 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16449 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16450 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16451 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16452 }
16453
16454 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16455 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16456 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16457}
16458
16459
16460/**
16461 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16462 */
16463HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16464{
16465 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16466
16467 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16468 {
16469 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16470 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16471 }
16472
16473 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16474}
16475
16476
16477/**
16478 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16479 * Conditional VM-exit.
16480 */
16481HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16482{
16483 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16484
16485 hmR0VmxReadExitQualVmcs(pVmxTransient);
16486 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16487
16488 VBOXSTRICTRC rcStrict;
16489 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16490 switch (uAccessType)
16491 {
16492 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16493 {
16494 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16495 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16496 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16497 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16498
16499 bool fIntercept;
16500 switch (iCrReg)
16501 {
16502 case 0:
16503 case 4:
16504 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16505 break;
16506
16507 case 3:
16508 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16509 break;
16510
16511 case 8:
16512 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16513 break;
16514
16515 default:
16516 fIntercept = false;
16517 break;
16518 }
16519 if (fIntercept)
16520 {
16521 VMXVEXITINFO ExitInfo;
16522 RT_ZERO(ExitInfo);
16523 ExitInfo.uReason = pVmxTransient->uExitReason;
16524 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16525 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16526 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16527 }
16528 else
16529 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16530 break;
16531 }
16532
16533 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16534 {
16535 /*
16536 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16537 * CR2 reads do not cause a VM-exit.
16538 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16539 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16540 */
16541 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16542 if ( iCrReg == 3
16543 || iCrReg == 8)
16544 {
16545 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16546 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16547 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16548 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
16549 {
16550 VMXVEXITINFO ExitInfo;
16551 RT_ZERO(ExitInfo);
16552 ExitInfo.uReason = pVmxTransient->uExitReason;
16553 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16554 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16555 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16556 }
16557 else
16558 {
16559 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16560 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16561 }
16562 }
16563 else
16564 {
16565 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16566 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16567 }
16568 break;
16569 }
16570
16571 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16572 {
16573 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16574 Assert(pVmcsNstGst);
16575 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16576 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16577 if ( (uGstHostMask & X86_CR0_TS)
16578 && (uReadShadow & X86_CR0_TS))
16579 {
16580 VMXVEXITINFO ExitInfo;
16581 RT_ZERO(ExitInfo);
16582 ExitInfo.uReason = pVmxTransient->uExitReason;
16583 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16584 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16585 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16586 }
16587 else
16588 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16589 break;
16590 }
16591
16592 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16593 {
16594 RTGCPTR GCPtrEffDst;
16595 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16596 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16597 if (fMemOperand)
16598 {
16599 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16600 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16601 }
16602 else
16603 GCPtrEffDst = NIL_RTGCPTR;
16604
16605 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
16606 {
16607 VMXVEXITINFO ExitInfo;
16608 RT_ZERO(ExitInfo);
16609 ExitInfo.uReason = pVmxTransient->uExitReason;
16610 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16611 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16612 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16613 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16614 }
16615 else
16616 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16617 break;
16618 }
16619
16620 default:
16621 {
16622 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16623 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16624 }
16625 }
16626
16627 if (rcStrict == VINF_IEM_RAISED_XCPT)
16628 {
16629 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16630 rcStrict = VINF_SUCCESS;
16631 }
16632 return rcStrict;
16633}
16634
16635
16636/**
16637 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16638 * Conditional VM-exit.
16639 */
16640HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16641{
16642 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16643
16644 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16645 {
16646 hmR0VmxReadExitQualVmcs(pVmxTransient);
16647 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16648
16649 VMXVEXITINFO ExitInfo;
16650 RT_ZERO(ExitInfo);
16651 ExitInfo.uReason = pVmxTransient->uExitReason;
16652 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16653 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16654 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16655 }
16656 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16657}
16658
16659
16660/**
16661 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16662 * Conditional VM-exit.
16663 */
16664HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16665{
16666 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16667
16668 hmR0VmxReadExitQualVmcs(pVmxTransient);
16669
16670 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16671 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16672 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16673
16674 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16675 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16676 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16677 {
16678 /*
16679 * IN/OUT instruction:
16680 * - Provides VM-exit instruction length.
16681 *
16682 * INS/OUTS instruction:
16683 * - Provides VM-exit instruction length.
16684 * - Provides Guest-linear address.
16685 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16686 */
16687 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16688 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16689
16690 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16691 pVmxTransient->ExitInstrInfo.u = 0;
16692 pVmxTransient->uGuestLinearAddr = 0;
16693
16694 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16695 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16696 if (fIOString)
16697 {
16698 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16699 if (fVmxInsOutsInfo)
16700 {
16701 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16702 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16703 }
16704 }
16705
16706 VMXVEXITINFO ExitInfo;
16707 RT_ZERO(ExitInfo);
16708 ExitInfo.uReason = pVmxTransient->uExitReason;
16709 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16710 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16711 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16712 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16713 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16714 }
16715 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16716}
16717
16718
16719/**
16720 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16721 */
16722HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16723{
16724 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16725
16726 uint32_t fMsrpm;
16727 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16728 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16729 else
16730 fMsrpm = VMXMSRPM_EXIT_RD;
16731
16732 if (fMsrpm & VMXMSRPM_EXIT_RD)
16733 {
16734 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16735 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16736 }
16737 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16738}
16739
16740
16741/**
16742 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16743 */
16744HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16745{
16746 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16747
16748 uint32_t fMsrpm;
16749 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16750 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16751 else
16752 fMsrpm = VMXMSRPM_EXIT_WR;
16753
16754 if (fMsrpm & VMXMSRPM_EXIT_WR)
16755 {
16756 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16757 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16758 }
16759 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16760}
16761
16762
16763/**
16764 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16765 */
16766HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16767{
16768 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16769
16770 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16771 {
16772 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16773 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16774 }
16775 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16776}
16777
16778
16779/**
16780 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16781 * VM-exit.
16782 */
16783HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16784{
16785 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16786
16787 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16788 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16789 VMXVEXITINFO ExitInfo;
16790 RT_ZERO(ExitInfo);
16791 ExitInfo.uReason = pVmxTransient->uExitReason;
16792 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16793 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16794}
16795
16796
16797/**
16798 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16799 */
16800HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16801{
16802 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16803
16804 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16805 {
16806 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16807 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16808 }
16809 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16810}
16811
16812
16813/**
16814 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16815 */
16816HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16817{
16818 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16819
16820 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16821 * PAUSE when executing a nested-guest? If it does not, we would not need
16822 * to check for the intercepts here. Just call VM-exit... */
16823
16824 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16825 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16826 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16827 {
16828 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16829 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16830 }
16831 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16832}
16833
16834
16835/**
16836 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16837 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16838 */
16839HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16840{
16841 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16842
16843 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16844 {
16845 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16846 VMXVEXITINFO ExitInfo;
16847 RT_ZERO(ExitInfo);
16848 ExitInfo.uReason = pVmxTransient->uExitReason;
16849 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16850 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16851 }
16852 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16853}
16854
16855
16856/**
16857 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16858 * VM-exit.
16859 */
16860HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16861{
16862 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16863
16864 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16865 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16866 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16867 hmR0VmxReadExitQualVmcs(pVmxTransient);
16868
16869 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16870
16871 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16872 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16873
16874 VMXVEXITINFO ExitInfo;
16875 RT_ZERO(ExitInfo);
16876 ExitInfo.uReason = pVmxTransient->uExitReason;
16877 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16878 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16879
16880 VMXVEXITEVENTINFO ExitEventInfo;
16881 RT_ZERO(ExitEventInfo);
16882 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16883 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16884 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16885}
16886
16887
16888/**
16889 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16890 * Conditional VM-exit.
16891 */
16892HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16893{
16894 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16895
16896 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16897 hmR0VmxReadExitQualVmcs(pVmxTransient);
16898 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16899}
16900
16901
16902/**
16903 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16904 * Conditional VM-exit.
16905 */
16906HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16907{
16908 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16909
16910 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16911 hmR0VmxReadExitQualVmcs(pVmxTransient);
16912 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16913}
16914
16915
16916/**
16917 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16918 */
16919HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16920{
16921 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16922
16923 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16924 {
16925 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16926 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16927 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16928 }
16929 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16930}
16931
16932
16933/**
16934 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16935 */
16936HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16937{
16938 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16939
16940 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16941 {
16942 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16943 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16944 }
16945 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16946}
16947
16948
16949/**
16950 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16951 */
16952HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16953{
16954 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16955
16956 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16957 {
16958 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16959 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16960 hmR0VmxReadExitQualVmcs(pVmxTransient);
16961 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16962
16963 VMXVEXITINFO ExitInfo;
16964 RT_ZERO(ExitInfo);
16965 ExitInfo.uReason = pVmxTransient->uExitReason;
16966 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16967 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16968 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16969 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16970 }
16971 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16972}
16973
16974
16975/**
16976 * Nested-guest VM-exit handler for invalid-guest state
16977 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16978 */
16979HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16980{
16981 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16982
16983 /*
16984 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16985 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16986 * Handle it like it's in an invalid guest state of the outer guest.
16987 *
16988 * When the fast path is implemented, this should be changed to cause the corresponding
16989 * nested-guest VM-exit.
16990 */
16991 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
16992}
16993
16994
16995/**
16996 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
16997 * and only provide the instruction length.
16998 *
16999 * Unconditional VM-exit.
17000 */
17001HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17002{
17003 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17004
17005#ifdef VBOX_STRICT
17006 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17007 switch (pVmxTransient->uExitReason)
17008 {
17009 case VMX_EXIT_ENCLS:
17010 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17011 break;
17012
17013 case VMX_EXIT_VMFUNC:
17014 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17015 break;
17016 }
17017#endif
17018
17019 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17020 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
17021}
17022
17023
17024/**
17025 * Nested-guest VM-exit handler for instructions that provide instruction length as
17026 * well as more information.
17027 *
17028 * Unconditional VM-exit.
17029 */
17030HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
17031{
17032 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17033
17034#ifdef VBOX_STRICT
17035 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17036 switch (pVmxTransient->uExitReason)
17037 {
17038 case VMX_EXIT_GDTR_IDTR_ACCESS:
17039 case VMX_EXIT_LDTR_TR_ACCESS:
17040 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17041 break;
17042
17043 case VMX_EXIT_RDRAND:
17044 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17045 break;
17046
17047 case VMX_EXIT_RDSEED:
17048 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17049 break;
17050
17051 case VMX_EXIT_XSAVES:
17052 case VMX_EXIT_XRSTORS:
17053 /** @todo NSTVMX: Verify XSS-bitmap. */
17054 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17055 break;
17056
17057 case VMX_EXIT_UMWAIT:
17058 case VMX_EXIT_TPAUSE:
17059 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17060 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17061 break;
17062 }
17063#endif
17064
17065 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17066 hmR0VmxReadExitQualVmcs(pVmxTransient);
17067 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17068
17069 VMXVEXITINFO ExitInfo;
17070 RT_ZERO(ExitInfo);
17071 ExitInfo.uReason = pVmxTransient->uExitReason;
17072 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17073 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17074 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17075 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17076}
17077
17078/** @} */
17079#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17080
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