VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Continue in ring-0 after making #BP pending for injection in the #BP VM-exit handler rather than going to ring-3.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 700.9 KB
Line 
1/* $Id: HMVMXR0.cpp 80273 2019-08-14 14:13:56Z 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/vm.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
87/** All the VMCS fields required for processing of exception/NMI VM-exits. */
88#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
89 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
90 | HMVMX_READ_EXIT_INSTR_LEN \
91 | HMVMX_READ_IDT_VECTORING_INFO \
92 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
93
94/** Assert that all the given fields have been read from the VMCS. */
95#ifdef VBOX_STRICT
96# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
97 do { \
98 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
99 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE(); \
100 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
101 } while (0)
102#else
103# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
104#endif
105
106/**
107 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
108 * guest using hardware-assisted VMX.
109 *
110 * This excludes state like GPRs (other than RSP) which are always are
111 * swapped and restored across the world-switch and also registers like EFER,
112 * MSR which cannot be modified by the guest without causing a VM-exit.
113 */
114#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
115 | CPUMCTX_EXTRN_RFLAGS \
116 | CPUMCTX_EXTRN_RSP \
117 | CPUMCTX_EXTRN_SREG_MASK \
118 | CPUMCTX_EXTRN_TABLE_MASK \
119 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
120 | CPUMCTX_EXTRN_SYSCALL_MSRS \
121 | CPUMCTX_EXTRN_SYSENTER_MSRS \
122 | CPUMCTX_EXTRN_TSC_AUX \
123 | CPUMCTX_EXTRN_OTHER_MSRS \
124 | CPUMCTX_EXTRN_CR0 \
125 | CPUMCTX_EXTRN_CR3 \
126 | CPUMCTX_EXTRN_CR4 \
127 | CPUMCTX_EXTRN_DR7 \
128 | CPUMCTX_EXTRN_HWVIRT \
129 | CPUMCTX_EXTRN_HM_VMX_MASK)
130
131/**
132 * Exception bitmap mask for real-mode guests (real-on-v86).
133 *
134 * We need to intercept all exceptions manually except:
135 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
136 * due to bugs in Intel CPUs.
137 * - \#PF need not be intercepted even in real-mode if we have nested paging
138 * support.
139 */
140#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
141 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
142 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
143 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
144 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
145 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
146 | RT_BIT(X86_XCPT_XF))
147
148/** Maximum VM-instruction error number. */
149#define HMVMX_INSTR_ERROR_MAX 28
150
151/** Profiling macro. */
152#ifdef HM_PROFILE_EXIT_DISPATCH
153# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
155#else
156# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
157# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
158#endif
159
160/** Assert that preemption is disabled or covered by thread-context hooks. */
161#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
162 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
163
164/** Assert that we haven't migrated CPUs when thread-context hooks are not
165 * used. */
166#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
167 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
168 ("Illegal migration! Entered on CPU %u Current %u\n", \
169 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
170
171/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
172 * context. */
173#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
174 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
175 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
176
177/** Log the VM-exit reason with an easily visible marker to identify it in a
178 * potential sea of logging data. */
179#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
180 do { \
181 Log4(("VM-exit: vcpu[%RU32] %85s -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-\n", (a_pVCpu)->idCpu, \
182 HMGetVmxExitName(a_uExitReason))); \
183 } while (0) \
184
185
186/*********************************************************************************************************************************
187* Structures and Typedefs *
188*********************************************************************************************************************************/
189/**
190 * VMX per-VCPU transient state.
191 *
192 * A state structure for holding miscellaneous information across
193 * VMX non-root operation and restored after the transition.
194 */
195typedef struct VMXTRANSIENT
196{
197 /** The host's rflags/eflags. */
198 RTCCUINTREG fEFlags;
199
200 /** The guest's TPR value used for TPR shadowing. */
201 uint8_t u8GuestTpr;
202 /** Alignment. */
203 uint8_t abAlignment0[7];
204
205 /** The basic VM-exit reason. */
206 uint16_t uExitReason;
207 /** Alignment. */
208 uint16_t u16Alignment0;
209 /** The VM-exit interruption error code. */
210 uint32_t uExitIntErrorCode;
211 /** The VM-exit exit code qualification. */
212 uint64_t uExitQual;
213 /** The Guest-linear address. */
214 uint64_t uGuestLinearAddr;
215 /** The Guest-physical address. */
216 uint64_t uGuestPhysicalAddr;
217
218 /** The VM-exit interruption-information field. */
219 uint32_t uExitIntInfo;
220 /** The VM-exit instruction-length field. */
221 uint32_t cbInstr;
222 /** The VM-exit instruction-information field. */
223 VMXEXITINSTRINFO ExitInstrInfo;
224 /** Whether the VM-entry failed or not. */
225 bool fVMEntryFailed;
226 /** Whether we are currently executing a nested-guest. */
227 bool fIsNestedGuest;
228 /** Alignment. */
229 uint8_t abAlignment1[2];
230
231 /** The VM-entry interruption-information field. */
232 uint32_t uEntryIntInfo;
233 /** The VM-entry exception error code field. */
234 uint32_t uEntryXcptErrorCode;
235 /** The VM-entry instruction length field. */
236 uint32_t cbEntryInstr;
237
238 /** IDT-vectoring information field. */
239 uint32_t uIdtVectoringInfo;
240 /** IDT-vectoring error code. */
241 uint32_t uIdtVectoringErrorCode;
242
243 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
244 uint32_t fVmcsFieldsRead;
245
246 /** Whether the guest debug state was active at the time of VM-exit. */
247 bool fWasGuestDebugStateActive;
248 /** Whether the hyper debug state was active at the time of VM-exit. */
249 bool fWasHyperDebugStateActive;
250 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
251 bool fUpdatedTscOffsettingAndPreemptTimer;
252 /** Whether the VM-exit was caused by a page-fault during delivery of a
253 * contributory exception or a page-fault. */
254 bool fVectoringDoublePF;
255 /** Whether the VM-exit was caused by a page-fault during delivery of an
256 * external interrupt or NMI. */
257 bool fVectoringPF;
258 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
259 * area after VM-exit. */
260 bool fRemoveTscAuxMsr;
261 bool afAlignment0[2];
262
263 /** The VMCS info. object. */
264 PVMXVMCSINFO pVmcsInfo;
265} VMXTRANSIENT;
266AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
267AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
268AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
269AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
270AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
271AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
272/** Pointer to VMX transient state. */
273typedef VMXTRANSIENT *PVMXTRANSIENT;
274/** Pointer to a const VMX transient state. */
275typedef const VMXTRANSIENT *PCVMXTRANSIENT;
276
277/**
278 * Memory operand read or write access.
279 */
280typedef enum VMXMEMACCESS
281{
282 VMXMEMACCESS_READ = 0,
283 VMXMEMACCESS_WRITE = 1
284} VMXMEMACCESS;
285
286/**
287 * VMX VM-exit handler.
288 *
289 * @returns Strict VBox status code (i.e. informational status codes too).
290 * @param pVCpu The cross context virtual CPU structure.
291 * @param pVmxTransient The VMX-transient structure.
292 */
293#ifndef HMVMX_USE_FUNCTION_TABLE
294typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
295#else
296typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
297/** Pointer to VM-exit handler. */
298typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
299#endif
300
301/**
302 * VMX VM-exit handler, non-strict status code.
303 *
304 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
305 *
306 * @returns VBox status code, no informational status code returned.
307 * @param pVCpu The cross context virtual CPU structure.
308 * @param pVmxTransient The VMX-transient structure.
309 *
310 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
311 * use of that status code will be replaced with VINF_EM_SOMETHING
312 * later when switching over to IEM.
313 */
314#ifndef HMVMX_USE_FUNCTION_TABLE
315typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
316#else
317typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
318#endif
319
320
321/*********************************************************************************************************************************
322* Internal Functions *
323*********************************************************************************************************************************/
324#ifndef HMVMX_USE_FUNCTION_TABLE
325DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
326# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
327# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
328#else
329# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
330# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
331#endif
332#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
333DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
334#endif
335
336static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
337
338/** @name VM-exit handler prototypes.
339 * @{
340 */
341static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
342static FNVMXEXITHANDLER hmR0VmxExitExtInt;
343static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
344static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
345static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
346static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
347static FNVMXEXITHANDLER hmR0VmxExitCpuid;
348static FNVMXEXITHANDLER hmR0VmxExitGetsec;
349static FNVMXEXITHANDLER hmR0VmxExitHlt;
350static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
351static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
352static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
353static FNVMXEXITHANDLER hmR0VmxExitVmcall;
354#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
355static FNVMXEXITHANDLER hmR0VmxExitVmclear;
356static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
357static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
358static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
359static FNVMXEXITHANDLER hmR0VmxExitVmread;
360static FNVMXEXITHANDLER hmR0VmxExitVmresume;
361static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
362static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
363static FNVMXEXITHANDLER hmR0VmxExitVmxon;
364static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
365#endif
366static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
367static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
368static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
369static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
370static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
371static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
372static FNVMXEXITHANDLER hmR0VmxExitMwait;
373static FNVMXEXITHANDLER hmR0VmxExitMtf;
374static FNVMXEXITHANDLER hmR0VmxExitMonitor;
375static FNVMXEXITHANDLER hmR0VmxExitPause;
376static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
377static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
378static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
379static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
380static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
381static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
382static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
383static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
384static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
385static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
386static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
387static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
388/** @} */
389
390#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
391/** @name Nested-guest VM-exit handler prototypes.
392 * @{
393 */
394static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
395static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
396static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
397static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
398static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
399static FNVMXEXITHANDLER hmR0VmxExitHltNested;
400static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
401static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
402static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
403static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
404static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
405static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
406static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
407static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
408static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
409static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
410static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
411static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
412static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
413static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
414static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
415static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
416static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
417static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
418static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
419static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
420static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
421static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
422static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
423/** @} */
424#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
425
426
427/*********************************************************************************************************************************
428* Global Variables *
429*********************************************************************************************************************************/
430#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
431/**
432 * Array of all VMCS fields.
433 * Any fields added to the VT-x spec. should be added here.
434 *
435 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
436 * of nested-guests.
437 */
438static const uint32_t g_aVmcsFields[] =
439{
440 /* 16-bit control fields. */
441 VMX_VMCS16_VPID,
442 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
443 VMX_VMCS16_EPTP_INDEX,
444
445 /* 16-bit guest-state fields. */
446 VMX_VMCS16_GUEST_ES_SEL,
447 VMX_VMCS16_GUEST_CS_SEL,
448 VMX_VMCS16_GUEST_SS_SEL,
449 VMX_VMCS16_GUEST_DS_SEL,
450 VMX_VMCS16_GUEST_FS_SEL,
451 VMX_VMCS16_GUEST_GS_SEL,
452 VMX_VMCS16_GUEST_LDTR_SEL,
453 VMX_VMCS16_GUEST_TR_SEL,
454 VMX_VMCS16_GUEST_INTR_STATUS,
455 VMX_VMCS16_GUEST_PML_INDEX,
456
457 /* 16-bits host-state fields. */
458 VMX_VMCS16_HOST_ES_SEL,
459 VMX_VMCS16_HOST_CS_SEL,
460 VMX_VMCS16_HOST_SS_SEL,
461 VMX_VMCS16_HOST_DS_SEL,
462 VMX_VMCS16_HOST_FS_SEL,
463 VMX_VMCS16_HOST_GS_SEL,
464 VMX_VMCS16_HOST_TR_SEL,
465
466 /* 64-bit control fields. */
467 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
468 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
469 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
470 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
471 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
472 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
473 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
474 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
475 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
476 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
477 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
478 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
479 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
480 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
481 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
482 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
483 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
484 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
485 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
486 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
487 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
488 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
489 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
490 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
491 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
492 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
493 VMX_VMCS64_CTRL_EPTP_FULL,
494 VMX_VMCS64_CTRL_EPTP_HIGH,
495 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
496 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
497 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
498 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
499 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
500 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
501 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
502 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
503 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
504 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
505 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
506 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
507 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
508 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
509 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
510 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
511 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
512 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
513 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
514 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
515 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
516 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
517
518 /* 64-bit read-only data fields. */
519 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
520 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
521
522 /* 64-bit guest-state fields. */
523 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
524 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
525 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
526 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
527 VMX_VMCS64_GUEST_PAT_FULL,
528 VMX_VMCS64_GUEST_PAT_HIGH,
529 VMX_VMCS64_GUEST_EFER_FULL,
530 VMX_VMCS64_GUEST_EFER_HIGH,
531 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
532 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
533 VMX_VMCS64_GUEST_PDPTE0_FULL,
534 VMX_VMCS64_GUEST_PDPTE0_HIGH,
535 VMX_VMCS64_GUEST_PDPTE1_FULL,
536 VMX_VMCS64_GUEST_PDPTE1_HIGH,
537 VMX_VMCS64_GUEST_PDPTE2_FULL,
538 VMX_VMCS64_GUEST_PDPTE2_HIGH,
539 VMX_VMCS64_GUEST_PDPTE3_FULL,
540 VMX_VMCS64_GUEST_PDPTE3_HIGH,
541 VMX_VMCS64_GUEST_BNDCFGS_FULL,
542 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
543
544 /* 64-bit host-state fields. */
545 VMX_VMCS64_HOST_PAT_FULL,
546 VMX_VMCS64_HOST_PAT_HIGH,
547 VMX_VMCS64_HOST_EFER_FULL,
548 VMX_VMCS64_HOST_EFER_HIGH,
549 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
550 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
551
552 /* 32-bit control fields. */
553 VMX_VMCS32_CTRL_PIN_EXEC,
554 VMX_VMCS32_CTRL_PROC_EXEC,
555 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
556 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
557 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
558 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
559 VMX_VMCS32_CTRL_EXIT,
560 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
561 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
562 VMX_VMCS32_CTRL_ENTRY,
563 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
564 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
565 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
566 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
567 VMX_VMCS32_CTRL_TPR_THRESHOLD,
568 VMX_VMCS32_CTRL_PROC_EXEC2,
569 VMX_VMCS32_CTRL_PLE_GAP,
570 VMX_VMCS32_CTRL_PLE_WINDOW,
571
572 /* 32-bits read-only fields. */
573 VMX_VMCS32_RO_VM_INSTR_ERROR,
574 VMX_VMCS32_RO_EXIT_REASON,
575 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
576 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
577 VMX_VMCS32_RO_IDT_VECTORING_INFO,
578 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
579 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
580 VMX_VMCS32_RO_EXIT_INSTR_INFO,
581
582 /* 32-bit guest-state fields. */
583 VMX_VMCS32_GUEST_ES_LIMIT,
584 VMX_VMCS32_GUEST_CS_LIMIT,
585 VMX_VMCS32_GUEST_SS_LIMIT,
586 VMX_VMCS32_GUEST_DS_LIMIT,
587 VMX_VMCS32_GUEST_FS_LIMIT,
588 VMX_VMCS32_GUEST_GS_LIMIT,
589 VMX_VMCS32_GUEST_LDTR_LIMIT,
590 VMX_VMCS32_GUEST_TR_LIMIT,
591 VMX_VMCS32_GUEST_GDTR_LIMIT,
592 VMX_VMCS32_GUEST_IDTR_LIMIT,
593 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
594 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
595 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
596 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
597 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
598 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
599 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
601 VMX_VMCS32_GUEST_INT_STATE,
602 VMX_VMCS32_GUEST_ACTIVITY_STATE,
603 VMX_VMCS32_GUEST_SMBASE,
604 VMX_VMCS32_GUEST_SYSENTER_CS,
605 VMX_VMCS32_PREEMPT_TIMER_VALUE,
606
607 /* 32-bit host-state fields. */
608 VMX_VMCS32_HOST_SYSENTER_CS,
609
610 /* Natural-width control fields. */
611 VMX_VMCS_CTRL_CR0_MASK,
612 VMX_VMCS_CTRL_CR4_MASK,
613 VMX_VMCS_CTRL_CR0_READ_SHADOW,
614 VMX_VMCS_CTRL_CR4_READ_SHADOW,
615 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
616 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
617 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
618 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
619
620 /* Natural-width read-only data fields. */
621 VMX_VMCS_RO_EXIT_QUALIFICATION,
622 VMX_VMCS_RO_IO_RCX,
623 VMX_VMCS_RO_IO_RSI,
624 VMX_VMCS_RO_IO_RDI,
625 VMX_VMCS_RO_IO_RIP,
626 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
627
628 /* Natural-width guest-state field */
629 VMX_VMCS_GUEST_CR0,
630 VMX_VMCS_GUEST_CR3,
631 VMX_VMCS_GUEST_CR4,
632 VMX_VMCS_GUEST_ES_BASE,
633 VMX_VMCS_GUEST_CS_BASE,
634 VMX_VMCS_GUEST_SS_BASE,
635 VMX_VMCS_GUEST_DS_BASE,
636 VMX_VMCS_GUEST_FS_BASE,
637 VMX_VMCS_GUEST_GS_BASE,
638 VMX_VMCS_GUEST_LDTR_BASE,
639 VMX_VMCS_GUEST_TR_BASE,
640 VMX_VMCS_GUEST_GDTR_BASE,
641 VMX_VMCS_GUEST_IDTR_BASE,
642 VMX_VMCS_GUEST_DR7,
643 VMX_VMCS_GUEST_RSP,
644 VMX_VMCS_GUEST_RIP,
645 VMX_VMCS_GUEST_RFLAGS,
646 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
647 VMX_VMCS_GUEST_SYSENTER_ESP,
648 VMX_VMCS_GUEST_SYSENTER_EIP,
649
650 /* Natural-width host-state fields */
651 VMX_VMCS_HOST_CR0,
652 VMX_VMCS_HOST_CR3,
653 VMX_VMCS_HOST_CR4,
654 VMX_VMCS_HOST_FS_BASE,
655 VMX_VMCS_HOST_GS_BASE,
656 VMX_VMCS_HOST_TR_BASE,
657 VMX_VMCS_HOST_GDTR_BASE,
658 VMX_VMCS_HOST_IDTR_BASE,
659 VMX_VMCS_HOST_SYSENTER_ESP,
660 VMX_VMCS_HOST_SYSENTER_EIP,
661 VMX_VMCS_HOST_RSP,
662 VMX_VMCS_HOST_RIP
663};
664#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
665
666static const uint32_t g_aVmcsSegBase[] =
667{
668 VMX_VMCS_GUEST_ES_BASE,
669 VMX_VMCS_GUEST_CS_BASE,
670 VMX_VMCS_GUEST_SS_BASE,
671 VMX_VMCS_GUEST_DS_BASE,
672 VMX_VMCS_GUEST_FS_BASE,
673 VMX_VMCS_GUEST_GS_BASE
674};
675static const uint32_t g_aVmcsSegSel[] =
676{
677 VMX_VMCS16_GUEST_ES_SEL,
678 VMX_VMCS16_GUEST_CS_SEL,
679 VMX_VMCS16_GUEST_SS_SEL,
680 VMX_VMCS16_GUEST_DS_SEL,
681 VMX_VMCS16_GUEST_FS_SEL,
682 VMX_VMCS16_GUEST_GS_SEL
683};
684static const uint32_t g_aVmcsSegLimit[] =
685{
686 VMX_VMCS32_GUEST_ES_LIMIT,
687 VMX_VMCS32_GUEST_CS_LIMIT,
688 VMX_VMCS32_GUEST_SS_LIMIT,
689 VMX_VMCS32_GUEST_DS_LIMIT,
690 VMX_VMCS32_GUEST_FS_LIMIT,
691 VMX_VMCS32_GUEST_GS_LIMIT
692};
693static const uint32_t g_aVmcsSegAttr[] =
694{
695 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
696 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
697 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
698 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
699 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
700 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
701};
702AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
703AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
704AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
705AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
706
707#ifdef HMVMX_USE_FUNCTION_TABLE
708/**
709 * VMX_EXIT dispatch table.
710 */
711static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
712{
713 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
714 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
715 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
716 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
717 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
718 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
719 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
720 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
721 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
722 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
723 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
724 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
725 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
726 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
727 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
728 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
729 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
730 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
731 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
732#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
733 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
734 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
735 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
736 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
737 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
738 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
739 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
740 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
741 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
742#else
743 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
744 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
745 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
746 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
747 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
748 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
749 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
750 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
751 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
752#endif
753 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
754 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
755 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
756 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
757 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
758 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
759 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
760 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
761 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
762 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
763 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
764 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
765 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
766 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
767 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
768 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
769 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
770 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
771 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
772 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
773 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
774 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
775 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
776 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
777 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
778#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
779 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
780#else
781 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
782#endif
783 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
784 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
785 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
786 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
787 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
788 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
789 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
790 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
791 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
792 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
793 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
794 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
795 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
796 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
797 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
798};
799#endif /* HMVMX_USE_FUNCTION_TABLE */
800
801#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
802static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
803{
804 /* 0 */ "(Not Used)",
805 /* 1 */ "VMCALL executed in VMX root operation.",
806 /* 2 */ "VMCLEAR with invalid physical address.",
807 /* 3 */ "VMCLEAR with VMXON pointer.",
808 /* 4 */ "VMLAUNCH with non-clear VMCS.",
809 /* 5 */ "VMRESUME with non-launched VMCS.",
810 /* 6 */ "VMRESUME after VMXOFF",
811 /* 7 */ "VM-entry with invalid control fields.",
812 /* 8 */ "VM-entry with invalid host state fields.",
813 /* 9 */ "VMPTRLD with invalid physical address.",
814 /* 10 */ "VMPTRLD with VMXON pointer.",
815 /* 11 */ "VMPTRLD with incorrect revision identifier.",
816 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
817 /* 13 */ "VMWRITE to read-only VMCS component.",
818 /* 14 */ "(Not Used)",
819 /* 15 */ "VMXON executed in VMX root operation.",
820 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
821 /* 17 */ "VM-entry with non-launched executing VMCS.",
822 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
823 /* 19 */ "VMCALL with non-clear VMCS.",
824 /* 20 */ "VMCALL with invalid VM-exit control fields.",
825 /* 21 */ "(Not Used)",
826 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
827 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
828 /* 24 */ "VMCALL with invalid SMM-monitor features.",
829 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
830 /* 26 */ "VM-entry with events blocked by MOV SS.",
831 /* 27 */ "(Not Used)",
832 /* 28 */ "Invalid operand to INVEPT/INVVPID."
833};
834#endif /* VBOX_STRICT && LOG_ENABLED */
835
836
837/**
838 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
839 *
840 * Any bit set in this mask is owned by the host/hypervisor and would cause a
841 * VM-exit when modified by the guest.
842 *
843 * @returns The static CR0 guest/host mask.
844 * @param pVCpu The cross context virtual CPU structure.
845 */
846DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
847{
848 /*
849 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
850 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
851 */
852 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
853 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
854 * and @bugref{6944}. */
855 PVM pVM = pVCpu->CTX_SUFF(pVM);
856 return ( X86_CR0_PE
857 | X86_CR0_NE
858 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
859 | X86_CR0_PG
860 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
861 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
862 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
863}
864
865
866/**
867 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
868 *
869 * Any bit set in this mask is owned by the host/hypervisor and would cause a
870 * VM-exit when modified by the guest.
871 *
872 * @returns The static CR4 guest/host mask.
873 * @param pVCpu The cross context virtual CPU structure.
874 */
875DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
876{
877 /*
878 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
879 * these bits are reserved on hardware that does not support them. Since the
880 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
881 * these bits and handle it depending on whether we expose them to the guest.
882 */
883 PVM pVM = pVCpu->CTX_SUFF(pVM);
884 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
885 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
886 return ( X86_CR4_VMXE
887 | X86_CR4_VME
888 | X86_CR4_PAE
889 | X86_CR4_PGE
890 | X86_CR4_PSE
891 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
892 | (fPcid ? X86_CR4_PCIDE : 0));
893}
894
895
896/**
897 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
898 * area.
899 *
900 * @returns @c true if it's different, @c false otherwise.
901 * @param pVmcsInfo The VMCS info. object.
902 */
903DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
904{
905 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
906 && pVmcsInfo->pvGuestMsrStore);
907}
908
909
910/**
911 * Sets the given Processor-based VM-execution controls.
912 *
913 * @param pVmxTransient The VMX-transient structure.
914 * @param uProcCtls The Processor-based VM-execution controls to set.
915 */
916static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
917{
918 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
919 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
920 {
921 pVmcsInfo->u32ProcCtls |= uProcCtls;
922 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
923 AssertRC(rc);
924 }
925}
926
927
928/**
929 * Removes the given Processor-based VM-execution controls.
930 *
931 * @param pVCpu The cross context virtual CPU structure.
932 * @param pVmxTransient The VMX-transient structure.
933 * @param uProcCtls The Processor-based VM-execution controls to remove.
934 *
935 * @remarks When executing a nested-guest, this will not remove any of the specified
936 * controls if the guest hypervisor has set any one of them.
937 */
938static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
939{
940 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
941 if (pVmcsInfo->u32ProcCtls & uProcCtls)
942 {
943#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
944 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
945 ? true
946 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
947#else
948 NOREF(pVCpu);
949 bool const fRemoveCtls = true;
950#endif
951 if (fRemoveCtls)
952 {
953 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
954 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
955 AssertRC(rc);
956 }
957 }
958}
959
960
961/**
962 * Sets the TSC offset for the current VMCS.
963 *
964 * @param uTscOffset The TSC offset to set.
965 * @param pVmcsInfo The VMCS info. object.
966 */
967static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
968{
969 if (pVmcsInfo->u64TscOffset != uTscOffset)
970 {
971 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
972 AssertRC(rc);
973 pVmcsInfo->u64TscOffset = uTscOffset;
974 }
975}
976
977
978/**
979 * Adds one or more exceptions to the exception bitmap and commits it to the current
980 * VMCS.
981 *
982 * @param pVmxTransient The VMX-transient structure.
983 * @param uXcptMask The exception(s) to add.
984 */
985static void hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
986{
987 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
988 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
989 if ((uXcptBitmap & uXcptMask) != uXcptMask)
990 {
991 uXcptBitmap |= uXcptMask;
992 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
993 AssertRC(rc);
994 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
995 }
996}
997
998
999/**
1000 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1001 *
1002 * @param pVmxTransient The VMX-transient structure.
1003 * @param uXcpt The exception to add.
1004 */
1005static void hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1006{
1007 Assert(uXcpt <= X86_XCPT_LAST);
1008 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1009}
1010
1011
1012/**
1013 * Remove one or more exceptions from the exception bitmap and commits it to the
1014 * current VMCS.
1015 *
1016 * This takes care of not removing the exception intercept if a nested-guest
1017 * requires the exception to be intercepted.
1018 *
1019 * @returns VBox status code.
1020 * @param pVCpu The cross context virtual CPU structure.
1021 * @param pVmxTransient The VMX-transient structure.
1022 * @param uXcptMask The exception(s) to remove.
1023 */
1024static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1025{
1026 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1027 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1028 if (u32XcptBitmap & uXcptMask)
1029 {
1030#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1031 if (!pVmxTransient->fIsNestedGuest)
1032 { /* likely */ }
1033 else
1034 {
1035 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1036 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1037 }
1038#endif
1039#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1040 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1041 | RT_BIT(X86_XCPT_DE)
1042 | RT_BIT(X86_XCPT_NM)
1043 | RT_BIT(X86_XCPT_TS)
1044 | RT_BIT(X86_XCPT_UD)
1045 | RT_BIT(X86_XCPT_NP)
1046 | RT_BIT(X86_XCPT_SS)
1047 | RT_BIT(X86_XCPT_GP)
1048 | RT_BIT(X86_XCPT_PF)
1049 | RT_BIT(X86_XCPT_MF));
1050#elif defined(HMVMX_ALWAYS_TRAP_PF)
1051 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1052#endif
1053 if (uXcptMask)
1054 {
1055 /* Validate we are not removing any essential exception intercepts. */
1056 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1057 NOREF(pVCpu);
1058 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1059 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1060
1061 /* Remove it from the exception bitmap. */
1062 u32XcptBitmap &= ~uXcptMask;
1063
1064 /* Commit and update the cache if necessary. */
1065 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1066 {
1067 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1068 AssertRC(rc);
1069 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1070 }
1071 }
1072 }
1073 return VINF_SUCCESS;
1074}
1075
1076
1077/**
1078 * Remove an exceptions from the exception bitmap and commits it to the current
1079 * VMCS.
1080 *
1081 * @returns VBox status code.
1082 * @param pVCpu The cross context virtual CPU structure.
1083 * @param pVmxTransient The VMX-transient structure.
1084 * @param uXcpt The exception to remove.
1085 */
1086static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1087{
1088 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1089}
1090
1091
1092/**
1093 * Loads the VMCS specified by the VMCS info. object.
1094 *
1095 * @returns VBox status code.
1096 * @param pVmcsInfo The VMCS info. object.
1097 *
1098 * @remarks Can be called with interrupts disabled.
1099 */
1100static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1101{
1102 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1103 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1104
1105 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1106 if (RT_SUCCESS(rc))
1107 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1108 return rc;
1109}
1110
1111
1112/**
1113 * Clears the VMCS specified by the VMCS info. object.
1114 *
1115 * @returns VBox status code.
1116 * @param pVmcsInfo The VMCS info. object.
1117 *
1118 * @remarks Can be called with interrupts disabled.
1119 */
1120static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1121{
1122 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1123 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1124
1125 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1126 if (RT_SUCCESS(rc))
1127 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1128 return rc;
1129}
1130
1131
1132#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1133/**
1134 * Loads the shadow VMCS specified by the VMCS info. object.
1135 *
1136 * @returns VBox status code.
1137 * @param pVmcsInfo The VMCS info. object.
1138 *
1139 * @remarks Can be called with interrupts disabled.
1140 */
1141static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1142{
1143 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1144 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1145
1146 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1147 if (RT_SUCCESS(rc))
1148 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1149 return rc;
1150}
1151
1152
1153/**
1154 * Clears the shadow VMCS specified by the VMCS info. object.
1155 *
1156 * @returns VBox status code.
1157 * @param pVmcsInfo The VMCS info. object.
1158 *
1159 * @remarks Can be called with interrupts disabled.
1160 */
1161static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1162{
1163 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1164 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1165
1166 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1167 if (RT_SUCCESS(rc))
1168 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1169 return rc;
1170}
1171
1172
1173/**
1174 * Switches from and to the specified VMCSes.
1175 *
1176 * @returns VBox status code.
1177 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1178 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1179 *
1180 * @remarks Called with interrupts disabled.
1181 */
1182static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1183{
1184 /*
1185 * Clear the VMCS we are switching out if it has not already been cleared.
1186 * This will sync any CPU internal data back to the VMCS.
1187 */
1188 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1189 {
1190 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1191 if (RT_SUCCESS(rc))
1192 {
1193 /*
1194 * The shadow VMCS, if any, would not be active at this point since we
1195 * would have cleared it while importing the virtual hardware-virtualization
1196 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1197 * clear the shadow VMCS here, just assert for safety.
1198 */
1199 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1200 }
1201 else
1202 return rc;
1203 }
1204
1205 /*
1206 * Clear the VMCS we are switching to if it has not already been cleared.
1207 * This will initialize the VMCS launch state to "clear" required for loading it.
1208 *
1209 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1210 */
1211 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1212 {
1213 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1214 if (RT_SUCCESS(rc))
1215 { /* likely */ }
1216 else
1217 return rc;
1218 }
1219
1220 /*
1221 * Finally, load the VMCS we are switching to.
1222 */
1223 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1224}
1225
1226
1227/**
1228 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1229 * caller.
1230 *
1231 * @returns VBox status code.
1232 * @param pVCpu The cross context virtual CPU structure.
1233 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1234 * true) or guest VMCS (pass false).
1235 */
1236static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1237{
1238 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1239 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1240
1241 PVMXVMCSINFO pVmcsInfoFrom;
1242 PVMXVMCSINFO pVmcsInfoTo;
1243 if (fSwitchToNstGstVmcs)
1244 {
1245 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1246 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1247 }
1248 else
1249 {
1250 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1251 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1252 }
1253
1254 /*
1255 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1256 * preemption hook code path acquires the current VMCS.
1257 */
1258 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1259
1260 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1261 if (RT_SUCCESS(rc))
1262 {
1263 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1264
1265 /*
1266 * If we are switching to a VMCS that was executed on a different host CPU or was
1267 * never executed before, flag that we need to export the host state before executing
1268 * guest/nested-guest code using hardware-assisted VMX.
1269 *
1270 * This could probably be done in a preemptible context since the preemption hook
1271 * will flag the necessary change in host context. However, since preemption is
1272 * already disabled and to avoid making assumptions about host specific code in
1273 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1274 * disabled.
1275 */
1276 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1277 { /* likely */ }
1278 else
1279 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1280
1281 ASMSetFlags(fEFlags);
1282
1283 /*
1284 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1285 * flag that we need to update the host MSR values there. Even if we decide in the
1286 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1287 * if its content differs, we would have to update the host MSRs anyway.
1288 */
1289 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1290 }
1291 else
1292 ASMSetFlags(fEFlags);
1293 return rc;
1294}
1295#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1296
1297
1298/**
1299 * Updates the VM's last error record.
1300 *
1301 * If there was a VMX instruction error, reads the error data from the VMCS and
1302 * updates VCPU's last error record as well.
1303 *
1304 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1305 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1306 * VERR_VMX_INVALID_VMCS_FIELD.
1307 * @param rc The error code.
1308 */
1309static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1310{
1311 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1312 || rc == VERR_VMX_UNABLE_TO_START_VM)
1313 {
1314 AssertPtrReturnVoid(pVCpu);
1315 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1316 }
1317 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1318}
1319
1320
1321#ifdef VBOX_STRICT
1322/**
1323 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1324 * transient structure.
1325 *
1326 * @param pVmxTransient The VMX-transient structure.
1327 */
1328DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1329{
1330 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1331 AssertRC(rc);
1332}
1333
1334
1335/**
1336 * Reads the VM-entry exception error code field from the VMCS into
1337 * the VMX transient structure.
1338 *
1339 * @param pVmxTransient The VMX-transient structure.
1340 */
1341DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1342{
1343 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1344 AssertRC(rc);
1345}
1346
1347
1348/**
1349 * Reads the VM-entry exception error code field from the VMCS into
1350 * the VMX transient structure.
1351 *
1352 * @param pVmxTransient The VMX-transient structure.
1353 */
1354DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1355{
1356 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1357 AssertRC(rc);
1358}
1359#endif /* VBOX_STRICT */
1360
1361
1362/**
1363 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1364 * transient structure.
1365 *
1366 * @param pVmxTransient The VMX-transient structure.
1367 */
1368DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1369{
1370 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1371 {
1372 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1373 AssertRC(rc);
1374 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1375 }
1376}
1377
1378
1379/**
1380 * Reads the VM-exit interruption error code from the VMCS into the VMX
1381 * transient structure.
1382 *
1383 * @param pVmxTransient The VMX-transient structure.
1384 */
1385DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1386{
1387 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1388 {
1389 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1390 AssertRC(rc);
1391 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1392 }
1393}
1394
1395
1396/**
1397 * Reads the VM-exit instruction length field from the VMCS into the VMX
1398 * transient structure.
1399 *
1400 * @param pVmxTransient The VMX-transient structure.
1401 */
1402DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1403{
1404 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1405 {
1406 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1407 AssertRC(rc);
1408 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1409 }
1410}
1411
1412
1413/**
1414 * Reads the VM-exit instruction-information field from the VMCS into
1415 * the VMX transient structure.
1416 *
1417 * @param pVmxTransient The VMX-transient structure.
1418 */
1419DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1420{
1421 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1422 {
1423 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1424 AssertRC(rc);
1425 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1426 }
1427}
1428
1429
1430/**
1431 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1432 *
1433 * @param pVmxTransient The VMX-transient structure.
1434 */
1435DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1436{
1437 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1438 {
1439 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1440 AssertRC(rc);
1441 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1442 }
1443}
1444
1445
1446/**
1447 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1448 *
1449 * @param pVmxTransient The VMX-transient structure.
1450 */
1451DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1452{
1453 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1454 {
1455 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1456 AssertRC(rc);
1457 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1458 }
1459}
1460
1461
1462/**
1463 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1464 *
1465 * @param pVmxTransient The VMX-transient structure.
1466 */
1467DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1468{
1469 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1470 {
1471 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1472 AssertRC(rc);
1473 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1474 }
1475}
1476
1477
1478/**
1479 * Reads the IDT-vectoring information field from the VMCS into the VMX
1480 * transient structure.
1481 *
1482 * @param pVmxTransient The VMX-transient structure.
1483 *
1484 * @remarks No-long-jump zone!!!
1485 */
1486DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1487{
1488 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1489 {
1490 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1491 AssertRC(rc);
1492 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1493 }
1494}
1495
1496
1497/**
1498 * Reads the IDT-vectoring error code from the VMCS into the VMX
1499 * transient structure.
1500 *
1501 * @param pVmxTransient The VMX-transient structure.
1502 */
1503DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1504{
1505 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1506 {
1507 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1508 AssertRC(rc);
1509 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1510 }
1511}
1512
1513#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1514/**
1515 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1516 *
1517 * @param pVmxTransient The VMX-transient structure.
1518 */
1519static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1520{
1521 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1522 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1523 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1524 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1525 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1526 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1527 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1528 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1529 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1530 AssertRC(rc);
1531 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1532 | HMVMX_READ_EXIT_INSTR_LEN
1533 | HMVMX_READ_EXIT_INSTR_INFO
1534 | HMVMX_READ_IDT_VECTORING_INFO
1535 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1536 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1537 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1538 | HMVMX_READ_GUEST_LINEAR_ADDR
1539 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1540}
1541#endif
1542
1543/**
1544 * Enters VMX root mode operation on the current CPU.
1545 *
1546 * @returns VBox status code.
1547 * @param pVM The cross context VM structure. Can be
1548 * NULL, after a resume.
1549 * @param HCPhysCpuPage Physical address of the VMXON region.
1550 * @param pvCpuPage Pointer to the VMXON region.
1551 */
1552static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1553{
1554 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1555 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1556 Assert(pvCpuPage);
1557 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1558
1559 if (pVM)
1560 {
1561 /* Write the VMCS revision identifier to the VMXON region. */
1562 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1563 }
1564
1565 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1566 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1567
1568 /* Enable the VMX bit in CR4 if necessary. */
1569 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1570
1571 /* Enter VMX root mode. */
1572 int rc = VMXEnable(HCPhysCpuPage);
1573 if (RT_FAILURE(rc))
1574 {
1575 if (!(uOldCr4 & X86_CR4_VMXE))
1576 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1577
1578 if (pVM)
1579 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1580 }
1581
1582 /* Restore interrupts. */
1583 ASMSetFlags(fEFlags);
1584 return rc;
1585}
1586
1587
1588/**
1589 * Exits VMX root mode operation on the current CPU.
1590 *
1591 * @returns VBox status code.
1592 */
1593static int hmR0VmxLeaveRootMode(void)
1594{
1595 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1596
1597 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1598 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1599
1600 /* If we're for some reason not in VMX root mode, then don't leave it. */
1601 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1602
1603 int rc;
1604 if (uHostCr4 & X86_CR4_VMXE)
1605 {
1606 /* Exit VMX root mode and clear the VMX bit in CR4. */
1607 VMXDisable();
1608 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1609 rc = VINF_SUCCESS;
1610 }
1611 else
1612 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1613
1614 /* Restore interrupts. */
1615 ASMSetFlags(fEFlags);
1616 return rc;
1617}
1618
1619
1620/**
1621 * Allocates and maps a physically contiguous page. The allocated page is
1622 * zero'd out (used by various VT-x structures).
1623 *
1624 * @returns IPRT status code.
1625 * @param pMemObj Pointer to the ring-0 memory object.
1626 * @param ppVirt Where to store the virtual address of the allocation.
1627 * @param pHCPhys Where to store the physical address of the allocation.
1628 */
1629static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1630{
1631 AssertPtr(pMemObj);
1632 AssertPtr(ppVirt);
1633 AssertPtr(pHCPhys);
1634 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1635 if (RT_FAILURE(rc))
1636 return rc;
1637 *ppVirt = RTR0MemObjAddress(*pMemObj);
1638 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1639 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1640 return VINF_SUCCESS;
1641}
1642
1643
1644/**
1645 * Frees and unmaps an allocated, physical page.
1646 *
1647 * @param pMemObj Pointer to the ring-0 memory object.
1648 * @param ppVirt Where to re-initialize the virtual address of allocation as
1649 * 0.
1650 * @param pHCPhys Where to re-initialize the physical address of the
1651 * allocation as 0.
1652 */
1653static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1654{
1655 AssertPtr(pMemObj);
1656 AssertPtr(ppVirt);
1657 AssertPtr(pHCPhys);
1658 /* NULL is valid, accepted and ignored by the free function below. */
1659 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1660 *pMemObj = NIL_RTR0MEMOBJ;
1661 *ppVirt = NULL;
1662 *pHCPhys = NIL_RTHCPHYS;
1663}
1664
1665
1666/**
1667 * Initializes a VMCS info. object.
1668 *
1669 * @param pVmcsInfo The VMCS info. object.
1670 */
1671static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1672{
1673 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1674
1675 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1676 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1677 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1678 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1679 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1680 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1681 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1682 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1683 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1684 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1685 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1686 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1687 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1688 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1689 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1690 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1691}
1692
1693
1694/**
1695 * Frees the VT-x structures for a VMCS info. object.
1696 *
1697 * @param pVM The cross context VM structure.
1698 * @param pVmcsInfo The VMCS info. object.
1699 */
1700static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1701{
1702 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1703
1704#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1705 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1706 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1707#endif
1708
1709 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1710 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1711
1712 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1713 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1714 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1715
1716 hmR0VmxInitVmcsInfo(pVmcsInfo);
1717}
1718
1719
1720/**
1721 * Allocates the VT-x structures for a VMCS info. object.
1722 *
1723 * @returns VBox status code.
1724 * @param pVCpu The cross context virtual CPU structure.
1725 * @param pVmcsInfo The VMCS info. object.
1726 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1727 */
1728static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1729{
1730 PVM pVM = pVCpu->CTX_SUFF(pVM);
1731
1732 /* Allocate the guest VM control structure (VMCS). */
1733 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1734 if (RT_SUCCESS(rc))
1735 {
1736 if (!fIsNstGstVmcs)
1737 {
1738#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1739 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1740 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1741#endif
1742 if (RT_SUCCESS(rc))
1743 {
1744 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1745 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1746 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1747 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1748 }
1749 }
1750 else
1751 {
1752 /* We don't yet support exposing VMCS shadowing to the guest. */
1753 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1754 Assert(!pVmcsInfo->pvShadowVmcs);
1755
1756 /* Get the allocated virtual-APIC page from CPUM. */
1757 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1758 {
1759 /** @todo NSTVMX: Get rid of this. There is no need to allocate a separate HC
1760 * page for this. Use the one provided by the nested-guest directly. */
1761 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1762 &pVmcsInfo->HCPhysVirtApic);
1763 Assert(pVmcsInfo->pbVirtApic);
1764 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1765 }
1766 }
1767
1768 if (RT_SUCCESS(rc))
1769 {
1770 /*
1771 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1772 * transparent accesses of specific MSRs.
1773 *
1774 * If the condition for enabling MSR bitmaps changes here, don't forget to
1775 * update HMIsMsrBitmapActive().
1776 *
1777 * We don't share MSR bitmaps between the guest and nested-guest as we then
1778 * don't need to care about carefully restoring the guest MSR bitmap.
1779 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1780 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1781 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1782 * we do that later while merging VMCS.
1783 */
1784 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1785 {
1786 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1787 if ( RT_SUCCESS(rc)
1788 && !fIsNstGstVmcs)
1789 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1790 }
1791
1792 if (RT_SUCCESS(rc))
1793 {
1794 /*
1795 * Allocate the VM-entry MSR-load area for the guest MSRs.
1796 *
1797 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1798 * the guest and nested-guest.
1799 */
1800 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1801 &pVmcsInfo->HCPhysGuestMsrLoad);
1802 if (RT_SUCCESS(rc))
1803 {
1804 /*
1805 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1806 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1807 */
1808 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1809 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1810 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1811
1812 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1813 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1814 &pVmcsInfo->HCPhysHostMsrLoad);
1815 }
1816 }
1817 }
1818 }
1819
1820 return rc;
1821}
1822
1823
1824/**
1825 * Free all VT-x structures for the VM.
1826 *
1827 * @returns IPRT status code.
1828 * @param pVM The cross context VM structure.
1829 */
1830static void hmR0VmxStructsFree(PVM pVM)
1831{
1832#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1833 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1834#endif
1835 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1836
1837#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1838 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1839 {
1840 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1841 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1842 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1843 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1844 }
1845#endif
1846
1847 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1848 {
1849 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1850 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1851 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1853 if (pVM->cpum.ro.GuestFeatures.fVmx)
1854 {
1855 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1856 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1857 }
1858#endif
1859 }
1860}
1861
1862
1863/**
1864 * Allocate all VT-x structures for the VM.
1865 *
1866 * @returns IPRT status code.
1867 * @param pVM The cross context VM structure.
1868 */
1869static int hmR0VmxStructsAlloc(PVM pVM)
1870{
1871 /*
1872 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1873 * The VMCS size cannot be more than 4096 bytes.
1874 *
1875 * See Intel spec. Appendix A.1 "Basic VMX Information".
1876 */
1877 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1878 if (cbVmcs <= X86_PAGE_4K_SIZE)
1879 { /* likely */ }
1880 else
1881 {
1882 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1883 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1884 }
1885
1886 /*
1887 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1888 */
1889#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1890 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1891 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1892 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1893#endif
1894
1895 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1896 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1897 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1898
1899 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1900 {
1901 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1902 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1903 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1904 }
1905
1906 /*
1907 * Allocate per-VM VT-x structures.
1908 */
1909 int rc = VINF_SUCCESS;
1910#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1911 /* Allocate crash-dump magic scratch page. */
1912 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1913 if (RT_FAILURE(rc))
1914 {
1915 hmR0VmxStructsFree(pVM);
1916 return rc;
1917 }
1918 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1919 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1920#endif
1921
1922 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1923 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1924 {
1925 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1926 &pVM->hm.s.vmx.HCPhysApicAccess);
1927 if (RT_FAILURE(rc))
1928 {
1929 hmR0VmxStructsFree(pVM);
1930 return rc;
1931 }
1932 }
1933
1934#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1935 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1936 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1937 {
1938 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1939 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1940 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1941 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1942 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1943 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1944 {
1945 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1946 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1947 if (RT_SUCCESS(rc))
1948 {
1949 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1950 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1951 }
1952 }
1953 else
1954 rc = VERR_NO_MEMORY;
1955
1956 if (RT_FAILURE(rc))
1957 {
1958 hmR0VmxStructsFree(pVM);
1959 return rc;
1960 }
1961 }
1962#endif
1963
1964 /*
1965 * Initialize per-VCPU VT-x structures.
1966 */
1967 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1968 {
1969 /* Allocate the guest VMCS structures. */
1970 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1971 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1972 if (RT_SUCCESS(rc))
1973 {
1974#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1975 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1976 if (pVM->cpum.ro.GuestFeatures.fVmx)
1977 {
1978 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1979 if (RT_SUCCESS(rc))
1980 { /* likely */ }
1981 else
1982 break;
1983 }
1984#endif
1985 }
1986 else
1987 break;
1988 }
1989
1990 if (RT_FAILURE(rc))
1991 {
1992 hmR0VmxStructsFree(pVM);
1993 return rc;
1994 }
1995
1996 return VINF_SUCCESS;
1997}
1998
1999#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2000/**
2001 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2002 *
2003 * @returns @c true if the MSR is intercepted, @c false otherwise.
2004 * @param pvMsrBitmap The MSR bitmap.
2005 * @param offMsr The MSR byte offset.
2006 * @param iBit The bit offset from the byte offset.
2007 */
2008DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2009{
2010 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2011 Assert(pbMsrBitmap);
2012 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2013 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2014}
2015#endif
2016
2017/**
2018 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2019 *
2020 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2021 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2022 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2023 * the read/write access of this MSR.
2024 *
2025 * @param pVCpu The cross context virtual CPU structure.
2026 * @param pVmcsInfo The VMCS info. object.
2027 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2028 * @param idMsr The MSR value.
2029 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2030 * include both a read -and- a write permission!
2031 *
2032 * @sa CPUMGetVmxMsrPermission.
2033 * @remarks Can be called with interrupts disabled.
2034 */
2035static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2036{
2037 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2038 Assert(pbMsrBitmap);
2039 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2040
2041 /*
2042 * MSR-bitmap Layout:
2043 * Byte index MSR range Interpreted as
2044 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2045 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2046 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2047 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2048 *
2049 * A bit corresponding to an MSR within the above range causes a VM-exit
2050 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2051 * the MSR range, it always cause a VM-exit.
2052 *
2053 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2054 */
2055 uint16_t const offBitmapRead = 0;
2056 uint16_t const offBitmapWrite = 0x800;
2057 uint16_t offMsr;
2058 int32_t iBit;
2059 if (idMsr <= UINT32_C(0x00001fff))
2060 {
2061 offMsr = 0;
2062 iBit = idMsr;
2063 }
2064 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2065 {
2066 offMsr = 0x400;
2067 iBit = idMsr - UINT32_C(0xc0000000);
2068 }
2069 else
2070 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2071
2072 /*
2073 * Set the MSR read permission.
2074 */
2075 uint16_t const offMsrRead = offBitmapRead + offMsr;
2076 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2077 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2078 {
2079#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2080 bool const fClear = !fIsNstGstVmcs ? true
2081 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2082#else
2083 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2084 bool const fClear = true;
2085#endif
2086 if (fClear)
2087 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2088 }
2089 else
2090 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2091
2092 /*
2093 * Set the MSR write permission.
2094 */
2095 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2096 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2097 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2098 {
2099#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2100 bool const fClear = !fIsNstGstVmcs ? true
2101 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2102#else
2103 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2104 bool const fClear = true;
2105#endif
2106 if (fClear)
2107 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2108 }
2109 else
2110 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2111}
2112
2113
2114/**
2115 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2116 * area.
2117 *
2118 * @returns VBox status code.
2119 * @param pVCpu The cross context virtual CPU structure.
2120 * @param pVmcsInfo The VMCS info. object.
2121 * @param cMsrs The number of MSRs.
2122 */
2123static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2124{
2125 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2126 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2127 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2128 {
2129 /* Commit the MSR counts to the VMCS and update the cache. */
2130 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2131 {
2132 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2133 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2134 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2135 pVmcsInfo->cEntryMsrLoad = cMsrs;
2136 pVmcsInfo->cExitMsrStore = cMsrs;
2137 pVmcsInfo->cExitMsrLoad = cMsrs;
2138 }
2139 return VINF_SUCCESS;
2140 }
2141
2142 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2143 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2144 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2145}
2146
2147
2148/**
2149 * Adds a new (or updates the value of an existing) guest/host MSR
2150 * pair to be swapped during the world-switch as part of the
2151 * auto-load/store MSR area in the VMCS.
2152 *
2153 * @returns VBox status code.
2154 * @param pVCpu The cross context virtual CPU structure.
2155 * @param pVmxTransient The VMX-transient structure.
2156 * @param idMsr The MSR.
2157 * @param uGuestMsrValue Value of the guest MSR.
2158 * @param fSetReadWrite Whether to set the guest read/write access of this
2159 * MSR (thus not causing a VM-exit).
2160 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2161 * necessary.
2162 */
2163static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2164 bool fSetReadWrite, bool fUpdateHostMsr)
2165{
2166 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2167 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2168 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2169 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2170 uint32_t i;
2171
2172 /* Paranoia. */
2173 Assert(pGuestMsrLoad);
2174
2175 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2176
2177 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2178 for (i = 0; i < cMsrs; i++)
2179 {
2180 if (pGuestMsrLoad[i].u32Msr == idMsr)
2181 break;
2182 }
2183
2184 bool fAdded = false;
2185 if (i == cMsrs)
2186 {
2187 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2188 ++cMsrs;
2189 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2190 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2191
2192 /* Set the guest to read/write this MSR without causing VM-exits. */
2193 if ( fSetReadWrite
2194 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2195 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2196
2197 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2198 fAdded = true;
2199 }
2200
2201 /* Update the MSR value for the newly added or already existing MSR. */
2202 pGuestMsrLoad[i].u32Msr = idMsr;
2203 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2204
2205 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2206 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2207 {
2208 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2209 pGuestMsrStore[i].u32Msr = idMsr;
2210 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2211 }
2212
2213 /* Update the corresponding slot in the host MSR area. */
2214 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2215 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2216 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2217 pHostMsr[i].u32Msr = idMsr;
2218
2219 /*
2220 * Only if the caller requests to update the host MSR value AND we've newly added the
2221 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2222 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2223 *
2224 * We do this for performance reasons since reading MSRs may be quite expensive.
2225 */
2226 if (fAdded)
2227 {
2228 if (fUpdateHostMsr)
2229 {
2230 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2231 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2232 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2233 }
2234 else
2235 {
2236 /* Someone else can do the work. */
2237 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2238 }
2239 }
2240 return VINF_SUCCESS;
2241}
2242
2243
2244/**
2245 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2246 * auto-load/store MSR area in the VMCS.
2247 *
2248 * @returns VBox status code.
2249 * @param pVCpu The cross context virtual CPU structure.
2250 * @param pVmxTransient The VMX-transient structure.
2251 * @param idMsr The MSR.
2252 */
2253static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2254{
2255 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2256 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2257 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2258 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2259
2260 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2261
2262 for (uint32_t i = 0; i < cMsrs; i++)
2263 {
2264 /* Find the MSR. */
2265 if (pGuestMsrLoad[i].u32Msr == idMsr)
2266 {
2267 /*
2268 * If it's the last MSR, we only need to reduce the MSR count.
2269 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2270 */
2271 if (i < cMsrs - 1)
2272 {
2273 /* Remove it from the VM-entry MSR-load area. */
2274 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2275 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2276
2277 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2278 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2279 {
2280 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2281 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2282 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2283 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2284 }
2285
2286 /* Remove it from the VM-exit MSR-load area. */
2287 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2288 Assert(pHostMsr[i].u32Msr == idMsr);
2289 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2290 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2291 }
2292
2293 /* Reduce the count to reflect the removed MSR and bail. */
2294 --cMsrs;
2295 break;
2296 }
2297 }
2298
2299 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2300 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2301 {
2302 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2303 AssertRCReturn(rc, rc);
2304
2305 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2306 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2307 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2308
2309 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2310 return VINF_SUCCESS;
2311 }
2312
2313 return VERR_NOT_FOUND;
2314}
2315
2316
2317/**
2318 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2319 *
2320 * @returns @c true if found, @c false otherwise.
2321 * @param pVmcsInfo The VMCS info. object.
2322 * @param idMsr The MSR to find.
2323 */
2324static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2325{
2326 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2327 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2328 Assert(pMsrs);
2329 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2330 for (uint32_t i = 0; i < cMsrs; i++)
2331 {
2332 if (pMsrs[i].u32Msr == idMsr)
2333 return true;
2334 }
2335 return false;
2336}
2337
2338
2339/**
2340 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2341 *
2342 * @param pVCpu The cross context virtual CPU structure.
2343 * @param pVmcsInfo The VMCS info. object.
2344 *
2345 * @remarks No-long-jump zone!!!
2346 */
2347static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2348{
2349 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2350
2351 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2352 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2353 Assert(pHostMsrLoad);
2354 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2355 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2356 for (uint32_t i = 0; i < cMsrs; i++)
2357 {
2358 /*
2359 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2360 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2361 */
2362 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2363 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2364 else
2365 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2366 }
2367}
2368
2369
2370/**
2371 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2372 * perform lazy restoration of the host MSRs while leaving VT-x.
2373 *
2374 * @param pVCpu The cross context virtual CPU structure.
2375 *
2376 * @remarks No-long-jump zone!!!
2377 */
2378static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2379{
2380 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2381
2382 /*
2383 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2384 */
2385 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2386 {
2387 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2388 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2389 {
2390 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2391 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2392 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2393 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2394 }
2395 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2396 }
2397}
2398
2399
2400/**
2401 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2402 * lazily while leaving VT-x.
2403 *
2404 * @returns true if it does, false otherwise.
2405 * @param pVCpu The cross context virtual CPU structure.
2406 * @param idMsr The MSR to check.
2407 */
2408static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2409{
2410 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2411 {
2412 switch (idMsr)
2413 {
2414 case MSR_K8_LSTAR:
2415 case MSR_K6_STAR:
2416 case MSR_K8_SF_MASK:
2417 case MSR_K8_KERNEL_GS_BASE:
2418 return true;
2419 }
2420 }
2421 return false;
2422}
2423
2424
2425/**
2426 * Loads a set of guests MSRs to allow read/passthru to the guest.
2427 *
2428 * The name of this function is slightly confusing. This function does NOT
2429 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2430 * common prefix for functions dealing with "lazy restoration" of the shared
2431 * MSRs.
2432 *
2433 * @param pVCpu The cross context virtual CPU structure.
2434 *
2435 * @remarks No-long-jump zone!!!
2436 */
2437static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2438{
2439 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2440 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2441
2442 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2443 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2444 {
2445 /*
2446 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2447 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2448 * we can skip a few MSR writes.
2449 *
2450 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2451 * guest MSR values in the guest-CPU context might be different to what's currently
2452 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2453 * CPU, see @bugref{8728}.
2454 */
2455 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2456 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2457 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2458 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2459 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2460 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2461 {
2462#ifdef VBOX_STRICT
2463 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2464 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2465 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2466 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2467#endif
2468 }
2469 else
2470 {
2471 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2472 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2473 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2474 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2475 }
2476 }
2477 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2478}
2479
2480
2481/**
2482 * Performs lazy restoration of the set of host MSRs if they were previously
2483 * loaded with guest MSR values.
2484 *
2485 * @param pVCpu The cross context virtual CPU structure.
2486 *
2487 * @remarks No-long-jump zone!!!
2488 * @remarks The guest MSRs should have been saved back into the guest-CPU
2489 * context by hmR0VmxImportGuestState()!!!
2490 */
2491static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2492{
2493 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2494 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2495
2496 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2497 {
2498 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2499 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2500 {
2501 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2502 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2503 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2504 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2505 }
2506 }
2507 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2508}
2509
2510
2511/**
2512 * Verifies that our cached values of the VMCS fields are all consistent with
2513 * what's actually present in the VMCS.
2514 *
2515 * @returns VBox status code.
2516 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2517 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2518 * VMCS content. HMCPU error-field is
2519 * updated, see VMX_VCI_XXX.
2520 * @param pVCpu The cross context virtual CPU structure.
2521 * @param pVmcsInfo The VMCS info. object.
2522 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2523 */
2524static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2525{
2526 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2527
2528 uint32_t u32Val;
2529 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2530 AssertRC(rc);
2531 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2532 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2533 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2534 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2535
2536 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2537 AssertRC(rc);
2538 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2539 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2540 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2541 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2542
2543 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2544 AssertRC(rc);
2545 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2546 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2547 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2548 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2549
2550 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2551 AssertRC(rc);
2552 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2553 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2554 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2555 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2556
2557 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2558 {
2559 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2560 AssertRC(rc);
2561 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2562 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2563 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2564 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2565 }
2566
2567 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2568 AssertRC(rc);
2569 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2570 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2571 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2572 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2573
2574 uint64_t u64Val;
2575 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2576 AssertRC(rc);
2577 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2578 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2579 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2580 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2581
2582 NOREF(pcszVmcs);
2583 return VINF_SUCCESS;
2584}
2585
2586
2587#ifdef VBOX_STRICT
2588/**
2589 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2590 *
2591 * @param pVCpu The cross context virtual CPU structure.
2592 * @param pVmcsInfo The VMCS info. object.
2593 */
2594static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2595{
2596 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2597
2598 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2599 {
2600 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2601 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2602 uint64_t uVmcsEferMsrVmcs;
2603 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2604 AssertRC(rc);
2605
2606 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2607 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2608 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2609 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2610 }
2611}
2612
2613
2614/**
2615 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2616 * VMCS are correct.
2617 *
2618 * @param pVCpu The cross context virtual CPU structure.
2619 * @param pVmcsInfo The VMCS info. object.
2620 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2621 */
2622static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2623{
2624 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2625
2626 /* Read the various MSR-area counts from the VMCS. */
2627 uint32_t cEntryLoadMsrs;
2628 uint32_t cExitStoreMsrs;
2629 uint32_t cExitLoadMsrs;
2630 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2631 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2632 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2633
2634 /* Verify all the MSR counts are the same. */
2635 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2636 Assert(cExitStoreMsrs == cExitLoadMsrs);
2637 uint32_t const cMsrs = cExitLoadMsrs;
2638
2639 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2640 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2641
2642 /* Verify the MSR counts are within the allocated page size. */
2643 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2644
2645 /* Verify the relevant contents of the MSR areas match. */
2646 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2647 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2648 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2649 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2650 for (uint32_t i = 0; i < cMsrs; i++)
2651 {
2652 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2653 if (fSeparateExitMsrStorePage)
2654 {
2655 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2656 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2657 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2658 }
2659
2660 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2661 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2662 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2663
2664 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2665 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2666 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2667 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2668
2669 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2670 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2671 if (fIsEferMsr)
2672 {
2673 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2674 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2675 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2676 }
2677
2678 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2679 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2680 {
2681 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2682 if (fIsEferMsr)
2683 {
2684 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2685 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2686 }
2687 else
2688 {
2689 if (!fIsNstGstVmcs)
2690 {
2691 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2692 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2693 }
2694 else
2695 {
2696 /*
2697 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2698 * execute a nested-guest with MSR passthrough.
2699 *
2700 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2701 * allow passthrough too.
2702 */
2703 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2704 Assert(pvMsrBitmapNstGst);
2705 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2706 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2707 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2708 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2709 }
2710 }
2711 }
2712
2713 /* Move to the next MSR. */
2714 pHostMsrLoad++;
2715 pGuestMsrLoad++;
2716 pGuestMsrStore++;
2717 }
2718}
2719#endif /* VBOX_STRICT */
2720
2721
2722/**
2723 * Flushes the TLB using EPT.
2724 *
2725 * @returns VBox status code.
2726 * @param pVCpu The cross context virtual CPU structure of the calling
2727 * EMT. Can be NULL depending on @a enmTlbFlush.
2728 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2729 * enmTlbFlush.
2730 * @param enmTlbFlush Type of flush.
2731 *
2732 * @remarks Caller is responsible for making sure this function is called only
2733 * when NestedPaging is supported and providing @a enmTlbFlush that is
2734 * supported by the CPU.
2735 * @remarks Can be called with interrupts disabled.
2736 */
2737static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2738{
2739 uint64_t au64Descriptor[2];
2740 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2741 au64Descriptor[0] = 0;
2742 else
2743 {
2744 Assert(pVCpu);
2745 Assert(pVmcsInfo);
2746 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2747 }
2748 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2749
2750 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2751 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2752
2753 if ( RT_SUCCESS(rc)
2754 && pVCpu)
2755 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2756}
2757
2758
2759/**
2760 * Flushes the TLB using VPID.
2761 *
2762 * @returns VBox status code.
2763 * @param pVCpu The cross context virtual CPU structure of the calling
2764 * EMT. Can be NULL depending on @a enmTlbFlush.
2765 * @param enmTlbFlush Type of flush.
2766 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2767 * on @a enmTlbFlush).
2768 *
2769 * @remarks Can be called with interrupts disabled.
2770 */
2771static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2772{
2773 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2774
2775 uint64_t au64Descriptor[2];
2776 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2777 {
2778 au64Descriptor[0] = 0;
2779 au64Descriptor[1] = 0;
2780 }
2781 else
2782 {
2783 AssertPtr(pVCpu);
2784 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2785 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2786 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2787 au64Descriptor[1] = GCPtr;
2788 }
2789
2790 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2791 AssertMsg(rc == VINF_SUCCESS,
2792 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2793
2794 if ( RT_SUCCESS(rc)
2795 && pVCpu)
2796 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2797 NOREF(rc);
2798}
2799
2800
2801/**
2802 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2803 * otherwise there is nothing really to invalidate.
2804 *
2805 * @returns VBox status code.
2806 * @param pVCpu The cross context virtual CPU structure.
2807 * @param GCVirt Guest virtual address of the page to invalidate.
2808 */
2809VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2810{
2811 AssertPtr(pVCpu);
2812 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2813
2814 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2815 {
2816 /*
2817 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2818 * the EPT case. See @bugref{6043} and @bugref{6177}.
2819 *
2820 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2821 * as this function maybe called in a loop with individual addresses.
2822 */
2823 PVM pVM = pVCpu->CTX_SUFF(pVM);
2824 if (pVM->hm.s.vmx.fVpid)
2825 {
2826 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2827 if (fVpidFlush)
2828 {
2829 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2830 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2831 }
2832 else
2833 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2834 }
2835 else if (pVM->hm.s.fNestedPaging)
2836 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2837 }
2838
2839 return VINF_SUCCESS;
2840}
2841
2842
2843/**
2844 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2845 * case where neither EPT nor VPID is supported by the CPU.
2846 *
2847 * @param pHostCpu The HM physical-CPU structure.
2848 * @param pVCpu The cross context virtual CPU structure.
2849 *
2850 * @remarks Called with interrupts disabled.
2851 */
2852static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2853{
2854 AssertPtr(pVCpu);
2855 AssertPtr(pHostCpu);
2856
2857 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2858
2859 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2860 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2861 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2862 pVCpu->hm.s.fForceTLBFlush = false;
2863 return;
2864}
2865
2866
2867/**
2868 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2869 *
2870 * @param pHostCpu The HM physical-CPU structure.
2871 * @param pVCpu The cross context virtual CPU structure.
2872 * @param pVmcsInfo The VMCS info. object.
2873 *
2874 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2875 * nomenclature. The reason is, to avoid confusion in compare statements
2876 * since the host-CPU copies are named "ASID".
2877 *
2878 * @remarks Called with interrupts disabled.
2879 */
2880static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2881{
2882#ifdef VBOX_WITH_STATISTICS
2883 bool fTlbFlushed = false;
2884# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2885# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2886 if (!fTlbFlushed) \
2887 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2888 } while (0)
2889#else
2890# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2891# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2892#endif
2893
2894 AssertPtr(pVCpu);
2895 AssertPtr(pHostCpu);
2896 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2897
2898 PVM pVM = pVCpu->CTX_SUFF(pVM);
2899 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2900 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2901 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2902
2903 /*
2904 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2905 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2906 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2907 * cannot reuse the current ASID anymore.
2908 */
2909 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2910 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2911 {
2912 ++pHostCpu->uCurrentAsid;
2913 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2914 {
2915 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2916 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2917 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2918 }
2919
2920 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2921 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2922 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2923
2924 /*
2925 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2926 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2927 */
2928 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2929 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2930 HMVMX_SET_TAGGED_TLB_FLUSHED();
2931 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2932 }
2933 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2934 {
2935 /*
2936 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2937 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2938 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2939 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2940 * mappings, see @bugref{6568}.
2941 *
2942 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2943 */
2944 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2945 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2946 HMVMX_SET_TAGGED_TLB_FLUSHED();
2947 }
2948 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
2949 {
2950 /*
2951 * The nested-guest specifies its own guest-physical address to use as the APIC-access
2952 * address which requires flushing the TLB of EPT cached structures.
2953 *
2954 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
2955 */
2956 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2957 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
2958 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
2959 HMVMX_SET_TAGGED_TLB_FLUSHED();
2960 }
2961
2962
2963 pVCpu->hm.s.fForceTLBFlush = false;
2964 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2965
2966 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2967 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2968 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2969 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2970 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2971 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2972 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2973 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2974 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
2975
2976 /* Update VMCS with the VPID. */
2977 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
2978 AssertRC(rc);
2979
2980#undef HMVMX_SET_TAGGED_TLB_FLUSHED
2981}
2982
2983
2984/**
2985 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
2986 *
2987 * @param pHostCpu The HM physical-CPU structure.
2988 * @param pVCpu The cross context virtual CPU structure.
2989 * @param pVmcsInfo The VMCS info. object.
2990 *
2991 * @remarks Called with interrupts disabled.
2992 */
2993static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2994{
2995 AssertPtr(pVCpu);
2996 AssertPtr(pHostCpu);
2997 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2998 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
2999 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3000
3001 /*
3002 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3003 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3004 */
3005 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3006 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3007 {
3008 pVCpu->hm.s.fForceTLBFlush = true;
3009 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3010 }
3011
3012 /* Check for explicit TLB flushes. */
3013 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3014 {
3015 pVCpu->hm.s.fForceTLBFlush = true;
3016 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3017 }
3018
3019 /* Check for TLB flushes while switching to/from a nested-guest. */
3020 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3021 {
3022 pVCpu->hm.s.fForceTLBFlush = true;
3023 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3024 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3025 }
3026
3027 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3028 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3029
3030 if (pVCpu->hm.s.fForceTLBFlush)
3031 {
3032 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3033 pVCpu->hm.s.fForceTLBFlush = false;
3034 }
3035}
3036
3037
3038/**
3039 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3040 *
3041 * @param pHostCpu The HM physical-CPU structure.
3042 * @param pVCpu The cross context virtual CPU structure.
3043 *
3044 * @remarks Called with interrupts disabled.
3045 */
3046static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3047{
3048 AssertPtr(pVCpu);
3049 AssertPtr(pHostCpu);
3050 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3051 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3052 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3053
3054 /*
3055 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3056 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3057 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3058 * cannot reuse the current ASID anymore.
3059 */
3060 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3061 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3062 {
3063 pVCpu->hm.s.fForceTLBFlush = true;
3064 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3065 }
3066
3067 /* Check for explicit TLB flushes. */
3068 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3069 {
3070 /*
3071 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3072 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3073 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3074 * include fExplicitFlush's too) - an obscure corner case.
3075 */
3076 pVCpu->hm.s.fForceTLBFlush = true;
3077 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3078 }
3079
3080 /* Check for TLB flushes while switching to/from a nested-guest. */
3081 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3082 {
3083 pVCpu->hm.s.fForceTLBFlush = true;
3084 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3085 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3086 }
3087
3088 PVM pVM = pVCpu->CTX_SUFF(pVM);
3089 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3090 if (pVCpu->hm.s.fForceTLBFlush)
3091 {
3092 ++pHostCpu->uCurrentAsid;
3093 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3094 {
3095 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3096 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3097 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3098 }
3099
3100 pVCpu->hm.s.fForceTLBFlush = false;
3101 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3102 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3103 if (pHostCpu->fFlushAsidBeforeUse)
3104 {
3105 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3106 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3107 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3108 {
3109 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3110 pHostCpu->fFlushAsidBeforeUse = false;
3111 }
3112 else
3113 {
3114 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3115 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3116 }
3117 }
3118 }
3119
3120 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3121 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3122 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3123 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3124 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3125 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3126 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3127
3128 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3129 AssertRC(rc);
3130}
3131
3132
3133/**
3134 * Flushes the guest TLB entry based on CPU capabilities.
3135 *
3136 * @param pHostCpu The HM physical-CPU structure.
3137 * @param pVCpu The cross context virtual CPU structure.
3138 * @param pVmcsInfo The VMCS info. object.
3139 *
3140 * @remarks Called with interrupts disabled.
3141 */
3142static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3143{
3144#ifdef HMVMX_ALWAYS_FLUSH_TLB
3145 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3146#endif
3147 PVM pVM = pVCpu->CTX_SUFF(pVM);
3148 switch (pVM->hm.s.vmx.enmTlbFlushType)
3149 {
3150 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3151 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3152 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3153 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3154 default:
3155 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3156 break;
3157 }
3158 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3159}
3160
3161
3162/**
3163 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3164 * TLB entries from the host TLB before VM-entry.
3165 *
3166 * @returns VBox status code.
3167 * @param pVM The cross context VM structure.
3168 */
3169static int hmR0VmxSetupTaggedTlb(PVM pVM)
3170{
3171 /*
3172 * Determine optimal flush type for nested paging.
3173 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3174 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3175 */
3176 if (pVM->hm.s.fNestedPaging)
3177 {
3178 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3179 {
3180 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3181 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3182 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3183 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3184 else
3185 {
3186 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3187 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3188 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3189 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3190 }
3191
3192 /* Make sure the write-back cacheable memory type for EPT is supported. */
3193 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3194 {
3195 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3196 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3197 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3198 }
3199
3200 /* EPT requires a page-walk length of 4. */
3201 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3202 {
3203 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3204 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3205 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3206 }
3207 }
3208 else
3209 {
3210 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3211 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3212 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3213 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3214 }
3215 }
3216
3217 /*
3218 * Determine optimal flush type for VPID.
3219 */
3220 if (pVM->hm.s.vmx.fVpid)
3221 {
3222 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3223 {
3224 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3225 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3226 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3227 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3228 else
3229 {
3230 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3231 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3232 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3233 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3234 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3235 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3236 pVM->hm.s.vmx.fVpid = false;
3237 }
3238 }
3239 else
3240 {
3241 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3242 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3243 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3244 pVM->hm.s.vmx.fVpid = false;
3245 }
3246 }
3247
3248 /*
3249 * Setup the handler for flushing tagged-TLBs.
3250 */
3251 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3252 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3253 else if (pVM->hm.s.fNestedPaging)
3254 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3255 else if (pVM->hm.s.vmx.fVpid)
3256 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3257 else
3258 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3259 return VINF_SUCCESS;
3260}
3261
3262
3263#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3264/**
3265 * Sets up the shadow VMCS fields arrays.
3266 *
3267 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3268 * executing the guest.
3269 *
3270 * @returns VBox status code.
3271 * @param pVM The cross context VM structure.
3272 */
3273static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3274{
3275 /*
3276 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3277 * when the host does not support it.
3278 */
3279 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3280 if ( !fGstVmwriteAll
3281 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3282 { /* likely. */ }
3283 else
3284 {
3285 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3286 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3287 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3288 }
3289
3290 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3291 uint32_t cRwFields = 0;
3292 uint32_t cRoFields = 0;
3293 for (uint32_t i = 0; i < cVmcsFields; i++)
3294 {
3295 VMXVMCSFIELD VmcsField;
3296 VmcsField.u = g_aVmcsFields[i];
3297
3298 /*
3299 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3300 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3301 * in the shadow VMCS fields array as they would be redundant.
3302 *
3303 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3304 * we must not include it in the shadow VMCS fields array. Guests attempting to
3305 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3306 * the required behavior.
3307 */
3308 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3309 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3310 {
3311 /*
3312 * Read-only fields are placed in a separate array so that while syncing shadow
3313 * VMCS fields later (which is more performance critical) we can avoid branches.
3314 *
3315 * However, if the guest can write to all fields (including read-only fields),
3316 * we treat it a as read/write field. Otherwise, writing to these fields would
3317 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3318 */
3319 if ( fGstVmwriteAll
3320 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3321 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3322 else
3323 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3324 }
3325 }
3326
3327 /* Update the counts. */
3328 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3329 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3330 return VINF_SUCCESS;
3331}
3332
3333
3334/**
3335 * Sets up the VMREAD and VMWRITE bitmaps.
3336 *
3337 * @param pVM The cross context VM structure.
3338 */
3339static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3340{
3341 /*
3342 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3343 */
3344 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3345 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3346 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3347 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3348 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3349
3350 /*
3351 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3352 * VMREAD and VMWRITE bitmaps.
3353 */
3354 {
3355 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3356 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3357 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3358 {
3359 uint32_t const uVmcsField = paShadowVmcsFields[i];
3360 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3361 Assert(uVmcsField >> 3 < cbBitmap);
3362 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3363 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3364 }
3365 }
3366
3367 /*
3368 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3369 * if the host supports VMWRITE to all supported VMCS fields.
3370 */
3371 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3372 {
3373 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3374 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3375 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3376 {
3377 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3378 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3379 Assert(uVmcsField >> 3 < cbBitmap);
3380 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3381 }
3382 }
3383}
3384#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3385
3386
3387/**
3388 * Sets up the virtual-APIC page address for the VMCS.
3389 *
3390 * @param pVmcsInfo The VMCS info. object.
3391 */
3392DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3393{
3394 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3395 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3396 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3397 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3398 AssertRC(rc);
3399}
3400
3401
3402/**
3403 * Sets up the MSR-bitmap address for the VMCS.
3404 *
3405 * @param pVmcsInfo The VMCS info. object.
3406 */
3407DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3408{
3409 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3410 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3411 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3412 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3413 AssertRC(rc);
3414}
3415
3416
3417/**
3418 * Sets up the APIC-access page address for the VMCS.
3419 *
3420 * @param pVCpu The cross context virtual CPU structure.
3421 */
3422DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3423{
3424 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3425 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3426 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3427 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3428 AssertRC(rc);
3429}
3430
3431
3432#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3433/**
3434 * Sets up the VMREAD bitmap address for the VMCS.
3435 *
3436 * @param pVCpu The cross context virtual CPU structure.
3437 */
3438DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3439{
3440 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3441 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3442 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3443 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3444 AssertRC(rc);
3445}
3446
3447
3448/**
3449 * Sets up the VMWRITE bitmap address for the VMCS.
3450 *
3451 * @param pVCpu The cross context virtual CPU structure.
3452 */
3453DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3454{
3455 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3456 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3457 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3458 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3459 AssertRC(rc);
3460}
3461#endif
3462
3463
3464/**
3465 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3466 * in the VMCS.
3467 *
3468 * @returns VBox status code.
3469 * @param pVmcsInfo The VMCS info. object.
3470 */
3471DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3472{
3473 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3474 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3475 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3476
3477 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3478 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3479 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3480
3481 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3482 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3483 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3484
3485 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3486 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3487 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3488 return VINF_SUCCESS;
3489}
3490
3491
3492/**
3493 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3494 *
3495 * @param pVCpu The cross context virtual CPU structure.
3496 * @param pVmcsInfo The VMCS info. object.
3497 */
3498static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3499{
3500 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3501
3502 /*
3503 * The guest can access the following MSRs (read, write) without causing
3504 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3505 */
3506 PVM pVM = pVCpu->CTX_SUFF(pVM);
3507 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3508 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3509 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3510 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3511 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3512
3513 /*
3514 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3515 * associated with then. We never need to intercept access (writes need to be
3516 * executed without causing a VM-exit, reads will #GP fault anyway).
3517 *
3518 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3519 * read/write them. We swap the the guest/host MSR value using the
3520 * auto-load/store MSR area.
3521 */
3522 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3523 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3524 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3525 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3526 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3527 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3528
3529 /*
3530 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3531 * required for 64-bit guests.
3532 */
3533 if (pVM->hm.s.fAllow64BitGuests)
3534 {
3535 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3536 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3537 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3538 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3539 }
3540
3541 /*
3542 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3543 */
3544#ifdef VBOX_STRICT
3545 Assert(pVmcsInfo->pvMsrBitmap);
3546 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3547 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3548#endif
3549}
3550
3551
3552/**
3553 * Sets up pin-based VM-execution controls in the VMCS.
3554 *
3555 * @returns VBox status code.
3556 * @param pVCpu The cross context virtual CPU structure.
3557 * @param pVmcsInfo The VMCS info. object.
3558 */
3559static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3560{
3561 PVM pVM = pVCpu->CTX_SUFF(pVM);
3562 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3563 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3564
3565 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3566 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3567
3568 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3569 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3570
3571 /* Enable the VMX-preemption timer. */
3572 if (pVM->hm.s.vmx.fUsePreemptTimer)
3573 {
3574 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3575 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3576 }
3577
3578#if 0
3579 /* Enable posted-interrupt processing. */
3580 if (pVM->hm.s.fPostedIntrs)
3581 {
3582 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3583 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3584 fVal |= VMX_PIN_CTLS_POSTED_INT;
3585 }
3586#endif
3587
3588 if ((fVal & fZap) != fVal)
3589 {
3590 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3591 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3592 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3593 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3594 }
3595
3596 /* Commit it to the VMCS and update our cache. */
3597 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3598 AssertRC(rc);
3599 pVmcsInfo->u32PinCtls = fVal;
3600
3601 return VINF_SUCCESS;
3602}
3603
3604
3605/**
3606 * Sets up secondary processor-based VM-execution controls in the VMCS.
3607 *
3608 * @returns VBox status code.
3609 * @param pVCpu The cross context virtual CPU structure.
3610 * @param pVmcsInfo The VMCS info. object.
3611 */
3612static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3613{
3614 PVM pVM = pVCpu->CTX_SUFF(pVM);
3615 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3616 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3617
3618 /* WBINVD causes a VM-exit. */
3619 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3620 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3621
3622 /* Enable EPT (aka nested-paging). */
3623 if (pVM->hm.s.fNestedPaging)
3624 fVal |= VMX_PROC_CTLS2_EPT;
3625
3626 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3627 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3628 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3629 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3630 fVal |= VMX_PROC_CTLS2_INVPCID;
3631
3632 /* Enable VPID. */
3633 if (pVM->hm.s.vmx.fVpid)
3634 fVal |= VMX_PROC_CTLS2_VPID;
3635
3636 /* Enable unrestricted guest execution. */
3637 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3638 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3639
3640#if 0
3641 if (pVM->hm.s.fVirtApicRegs)
3642 {
3643 /* Enable APIC-register virtualization. */
3644 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3645 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3646
3647 /* Enable virtual-interrupt delivery. */
3648 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3649 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3650 }
3651#endif
3652
3653 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3654 where the TPR shadow resides. */
3655 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3656 * done dynamically. */
3657 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3658 {
3659 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3660 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3661 }
3662
3663 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3664 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3665 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3666 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3667 fVal |= VMX_PROC_CTLS2_RDTSCP;
3668
3669 /* Enable Pause-Loop exiting. */
3670 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3671 && pVM->hm.s.vmx.cPleGapTicks
3672 && pVM->hm.s.vmx.cPleWindowTicks)
3673 {
3674 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3675
3676 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3677 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3678 }
3679
3680 if ((fVal & fZap) != fVal)
3681 {
3682 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3683 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3684 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3685 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3686 }
3687
3688 /* Commit it to the VMCS and update our cache. */
3689 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3690 AssertRC(rc);
3691 pVmcsInfo->u32ProcCtls2 = fVal;
3692
3693 return VINF_SUCCESS;
3694}
3695
3696
3697/**
3698 * Sets up processor-based VM-execution controls in the VMCS.
3699 *
3700 * @returns VBox status code.
3701 * @param pVCpu The cross context virtual CPU structure.
3702 * @param pVmcsInfo The VMCS info. object.
3703 */
3704static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3705{
3706 PVM pVM = pVCpu->CTX_SUFF(pVM);
3707
3708 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3709 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3710
3711 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3712 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3713 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3714 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3715 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3716 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3717 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3718
3719 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3720 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3721 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3722 {
3723 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3724 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3725 }
3726
3727 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3728 if (!pVM->hm.s.fNestedPaging)
3729 {
3730 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3731 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3732 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3733 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3734 }
3735
3736 /* Use TPR shadowing if supported by the CPU. */
3737 if ( PDMHasApic(pVM)
3738 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3739 {
3740 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3741 /* CR8 writes cause a VM-exit based on TPR threshold. */
3742 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3743 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3744 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3745 }
3746 else
3747 {
3748 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3749 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3750 if (pVM->hm.s.fAllow64BitGuests)
3751 {
3752 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3753 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3754 }
3755 }
3756
3757 /* Use MSR-bitmaps if supported by the CPU. */
3758 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3759 {
3760 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3761 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3762 }
3763
3764 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3765 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3766 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3767
3768 if ((fVal & fZap) != fVal)
3769 {
3770 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3771 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3772 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3773 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3774 }
3775
3776 /* Commit it to the VMCS and update our cache. */
3777 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3778 AssertRC(rc);
3779 pVmcsInfo->u32ProcCtls = fVal;
3780
3781 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3782 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3783 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3784
3785 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3786 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3787 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3788
3789 /* Sanity check, should not really happen. */
3790 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3791 { /* likely */ }
3792 else
3793 {
3794 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3795 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3796 }
3797
3798 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3799 return VINF_SUCCESS;
3800}
3801
3802
3803/**
3804 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3805 * Processor-based VM-execution) control fields in the VMCS.
3806 *
3807 * @returns VBox status code.
3808 * @param pVCpu The cross context virtual CPU structure.
3809 * @param pVmcsInfo The VMCS info. object.
3810 */
3811static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3812{
3813#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3814 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3815 {
3816 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3817 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3818 }
3819#endif
3820
3821 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3822 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3823 AssertRC(rc);
3824
3825 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3826 if (RT_SUCCESS(rc))
3827 {
3828 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3829 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3830
3831 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3832 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3833
3834 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3835 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3836 return VINF_SUCCESS;
3837 }
3838 else
3839 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3840 return rc;
3841}
3842
3843
3844/**
3845 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3846 *
3847 * We shall setup those exception intercepts that don't change during the
3848 * lifetime of the VM here. The rest are done dynamically while loading the
3849 * guest state.
3850 *
3851 * @param pVCpu The cross context virtual CPU structure.
3852 * @param pVmcsInfo The VMCS info. object.
3853 */
3854static void hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3855{
3856 /*
3857 * The following exceptions are always intercepted:
3858 *
3859 * #AC - To prevent the guest from hanging the CPU.
3860 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3861 * recursive #DBs can cause a CPU hang.
3862 * #PF - To sync our shadow page tables when nested-paging is not used.
3863 */
3864 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3865 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3866 | RT_BIT(X86_XCPT_DB)
3867 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3868
3869 /* Commit it to the VMCS. */
3870 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3871 AssertRC(rc);
3872
3873 /* Update our cache of the exception bitmap. */
3874 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3875}
3876
3877
3878#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3879/**
3880 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3881 *
3882 * @returns VBox status code.
3883 * @param pVCpu The cross context virtual CPU structure.
3884 * @param pVmcsInfo The VMCS info. object.
3885 */
3886static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3887{
3888 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3889 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3890 AssertRC(rc);
3891
3892 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3893 if (RT_SUCCESS(rc))
3894 {
3895 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3896 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3897 return VINF_SUCCESS;
3898 }
3899 else
3900 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3901 return rc;
3902}
3903#endif
3904
3905
3906/**
3907 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3908 * VMX.
3909 *
3910 * @returns VBox status code.
3911 * @param pVCpu The cross context virtual CPU structure.
3912 * @param pVmcsInfo The VMCS info. object.
3913 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3914 */
3915static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3916{
3917 Assert(pVmcsInfo->pvVmcs);
3918 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3919
3920 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3921 PVM pVM = pVCpu->CTX_SUFF(pVM);
3922 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3923 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3924
3925 LogFlowFunc(("\n"));
3926
3927 /*
3928 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3929 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3930 */
3931 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3932 if (RT_SUCCESS(rc))
3933 {
3934 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3935 if (RT_SUCCESS(rc))
3936 {
3937 if (!fIsNstGstVmcs)
3938 {
3939 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3940 if (RT_SUCCESS(rc))
3941 {
3942 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3943 if (RT_SUCCESS(rc))
3944 {
3945 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3946 if (RT_SUCCESS(rc))
3947 {
3948 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
3949#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3950 /*
3951 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
3952 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
3953 * making it fit for use when VMCS shadowing is later enabled.
3954 */
3955 if (pVmcsInfo->pvShadowVmcs)
3956 {
3957 VMXVMCSREVID VmcsRevId;
3958 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3959 VmcsRevId.n.fIsShadowVmcs = 1;
3960 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
3961 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
3962 if (RT_SUCCESS(rc))
3963 { /* likely */ }
3964 else
3965 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
3966 }
3967#endif
3968 }
3969 else
3970 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
3971 }
3972 else
3973 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
3974 }
3975 else
3976 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
3977 }
3978 else
3979 {
3980#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3981 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
3982 if (RT_SUCCESS(rc))
3983 { /* likely */ }
3984 else
3985 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
3986#else
3987 AssertFailed();
3988#endif
3989 }
3990 }
3991 else
3992 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
3993 }
3994 else
3995 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
3996
3997 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
3998 if (RT_SUCCESS(rc))
3999 {
4000 rc = hmR0VmxClearVmcs(pVmcsInfo);
4001 if (RT_SUCCESS(rc))
4002 { /* likely */ }
4003 else
4004 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4005 }
4006
4007 /*
4008 * Update the last-error record both for failures and success, so we
4009 * can propagate the status code back to ring-3 for diagnostics.
4010 */
4011 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4012 NOREF(pszVmcs);
4013 return rc;
4014}
4015
4016
4017/**
4018 * Does global VT-x initialization (called during module initialization).
4019 *
4020 * @returns VBox status code.
4021 */
4022VMMR0DECL(int) VMXR0GlobalInit(void)
4023{
4024#ifdef HMVMX_USE_FUNCTION_TABLE
4025 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4026# ifdef VBOX_STRICT
4027 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4028 Assert(g_apfnVMExitHandlers[i]);
4029# endif
4030#endif
4031 return VINF_SUCCESS;
4032}
4033
4034
4035/**
4036 * Does global VT-x termination (called during module termination).
4037 */
4038VMMR0DECL(void) VMXR0GlobalTerm()
4039{
4040 /* Nothing to do currently. */
4041}
4042
4043
4044/**
4045 * Sets up and activates VT-x on the current CPU.
4046 *
4047 * @returns VBox status code.
4048 * @param pHostCpu The HM physical-CPU structure.
4049 * @param pVM The cross context VM structure. Can be
4050 * NULL after a host resume operation.
4051 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4052 * fEnabledByHost is @c true).
4053 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4054 * @a fEnabledByHost is @c true).
4055 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4056 * enable VT-x on the host.
4057 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4058 */
4059VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4060 PCSUPHWVIRTMSRS pHwvirtMsrs)
4061{
4062 AssertPtr(pHostCpu);
4063 AssertPtr(pHwvirtMsrs);
4064 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4065
4066 /* Enable VT-x if it's not already enabled by the host. */
4067 if (!fEnabledByHost)
4068 {
4069 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4070 if (RT_FAILURE(rc))
4071 return rc;
4072 }
4073
4074 /*
4075 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4076 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4077 * invalidated when flushing by VPID.
4078 */
4079 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4080 {
4081 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4082 pHostCpu->fFlushAsidBeforeUse = false;
4083 }
4084 else
4085 pHostCpu->fFlushAsidBeforeUse = true;
4086
4087 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4088 ++pHostCpu->cTlbFlushes;
4089
4090 return VINF_SUCCESS;
4091}
4092
4093
4094/**
4095 * Deactivates VT-x on the current CPU.
4096 *
4097 * @returns VBox status code.
4098 * @param pvCpuPage Pointer to the VMXON region.
4099 * @param HCPhysCpuPage Physical address of the VMXON region.
4100 *
4101 * @remarks This function should never be called when SUPR0EnableVTx() or
4102 * similar was used to enable VT-x on the host.
4103 */
4104VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4105{
4106 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4107
4108 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4109 return hmR0VmxLeaveRootMode();
4110}
4111
4112
4113/**
4114 * Does per-VM VT-x initialization.
4115 *
4116 * @returns VBox status code.
4117 * @param pVM The cross context VM structure.
4118 */
4119VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4120{
4121 AssertPtr(pVM);
4122 LogFlowFunc(("pVM=%p\n", pVM));
4123
4124 int rc = hmR0VmxStructsAlloc(pVM);
4125 if (RT_FAILURE(rc))
4126 {
4127 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4128 return rc;
4129 }
4130
4131 return VINF_SUCCESS;
4132}
4133
4134
4135/**
4136 * Does per-VM VT-x termination.
4137 *
4138 * @returns VBox status code.
4139 * @param pVM The cross context VM structure.
4140 */
4141VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4142{
4143 AssertPtr(pVM);
4144 LogFlowFunc(("pVM=%p\n", pVM));
4145
4146#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4147 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4148 {
4149 Assert(pVM->hm.s.vmx.pvScratch);
4150 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4151 }
4152#endif
4153 hmR0VmxStructsFree(pVM);
4154 return VINF_SUCCESS;
4155}
4156
4157
4158/**
4159 * Sets up the VM for execution using hardware-assisted VMX.
4160 * This function is only called once per-VM during initialization.
4161 *
4162 * @returns VBox status code.
4163 * @param pVM The cross context VM structure.
4164 */
4165VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4166{
4167 AssertPtr(pVM);
4168 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4169
4170 LogFlowFunc(("pVM=%p\n", pVM));
4171
4172 /*
4173 * At least verify if VMX is enabled, since we can't check if we're in
4174 * VMX root mode or not without causing a #GP.
4175 */
4176 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4177 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4178 { /* likely */ }
4179 else
4180 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4181
4182 /*
4183 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4184 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4185 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4186 */
4187 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4188 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4189 || !pVM->hm.s.vmx.pRealModeTSS))
4190 {
4191 LogRelFunc(("Invalid real-on-v86 state.\n"));
4192 return VERR_INTERNAL_ERROR;
4193 }
4194
4195 /* Initialize these always, see hmR3InitFinalizeR0().*/
4196 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4197 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4198
4199 /* Setup the tagged-TLB flush handlers. */
4200 int rc = hmR0VmxSetupTaggedTlb(pVM);
4201 if (RT_FAILURE(rc))
4202 {
4203 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4204 return rc;
4205 }
4206
4207#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4208 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4209 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4210 {
4211 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4212 if (RT_SUCCESS(rc))
4213 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4214 else
4215 {
4216 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4217 return rc;
4218 }
4219 }
4220#endif
4221
4222 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4223 {
4224 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4225 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4226
4227 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4228 if (RT_SUCCESS(rc))
4229 {
4230#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4231 if (pVM->cpum.ro.GuestFeatures.fVmx)
4232 {
4233 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4234 if (RT_SUCCESS(rc))
4235 { /* likely */ }
4236 else
4237 {
4238 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4239 return rc;
4240 }
4241 }
4242#endif
4243 }
4244 else
4245 {
4246 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4247 return rc;
4248 }
4249 }
4250
4251 return VINF_SUCCESS;
4252}
4253
4254
4255/**
4256 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4257 * the VMCS.
4258 */
4259static void hmR0VmxExportHostControlRegs(void)
4260{
4261 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4262 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4263 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4264}
4265
4266
4267/**
4268 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4269 * the host-state area in the VMCS.
4270 *
4271 * @returns VBox status code.
4272 * @param pVCpu The cross context virtual CPU structure.
4273 */
4274static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4275{
4276/**
4277 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4278 * requirements. See hmR0VmxExportHostSegmentRegs().
4279 */
4280#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4281 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4282 { \
4283 bool fValidSelector = true; \
4284 if ((a_selValue) & X86_SEL_LDT) \
4285 { \
4286 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4287 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4288 } \
4289 if (fValidSelector) \
4290 { \
4291 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4292 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4293 } \
4294 (a_selValue) = 0; \
4295 }
4296
4297 /*
4298 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4299 * will be messed up. We should -not- save the messed up state without restoring
4300 * the original host-state, see @bugref{7240}.
4301 *
4302 * This apparently can happen (most likely the FPU changes), deal with it rather than
4303 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4304 */
4305 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4306 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4307 {
4308 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4309 pVCpu->idCpu));
4310 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4311 }
4312 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4313
4314 /*
4315 * Host segment registers.
4316 */
4317 RTSEL uSelES = ASMGetES();
4318 RTSEL uSelCS = ASMGetCS();
4319 RTSEL uSelSS = ASMGetSS();
4320 RTSEL uSelDS = ASMGetDS();
4321 RTSEL uSelFS = ASMGetFS();
4322 RTSEL uSelGS = ASMGetGS();
4323 RTSEL uSelTR = ASMGetTR();
4324
4325 /*
4326 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4327 * gain VM-entry and restore them before we get preempted.
4328 *
4329 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4330 */
4331 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4332 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4333 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4334 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4335
4336 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4337 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4338 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4339 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4340 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4341 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4342 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4343 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4344 Assert(uSelCS);
4345 Assert(uSelTR);
4346
4347 /* Write these host selector fields into the host-state area in the VMCS. */
4348 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4349 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4350 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4351 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4352 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4353 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4354 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4355
4356 /*
4357 * Host GDTR and IDTR.
4358 */
4359 RTGDTR Gdtr;
4360 RTIDTR Idtr;
4361 RT_ZERO(Gdtr);
4362 RT_ZERO(Idtr);
4363 ASMGetGDTR(&Gdtr);
4364 ASMGetIDTR(&Idtr);
4365 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4366 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4367
4368 /*
4369 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4370 * them to the maximum limit (0xffff) on every VM-exit.
4371 */
4372 if (Gdtr.cbGdt != 0xffff)
4373 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4374
4375 /*
4376 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4377 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4378 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4379 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4380 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4381 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4382 * at 0xffff on hosts where we are sure it won't cause trouble.
4383 */
4384#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4385 if (Idtr.cbIdt < 0x0fff)
4386#else
4387 if (Idtr.cbIdt != 0xffff)
4388#endif
4389 {
4390 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4391 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4392 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4393 }
4394
4395 /*
4396 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4397 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4398 * RPL should be too in most cases.
4399 */
4400 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4401 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4402
4403 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4404 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4405
4406 /*
4407 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4408 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4409 * restoration if the host has something else. Task switching is not supported in 64-bit
4410 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4411 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4412 *
4413 * [1] See Intel spec. 3.5 "System Descriptor Types".
4414 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4415 */
4416 PVM pVM = pVCpu->CTX_SUFF(pVM);
4417 Assert(pDesc->System.u4Type == 11);
4418 if ( pDesc->System.u16LimitLow != 0x67
4419 || pDesc->System.u4LimitHigh)
4420 {
4421 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4422 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4423 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4424 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4425 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4426 }
4427
4428 /*
4429 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4430 */
4431 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4432 {
4433 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4434 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4435 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4436 {
4437 /* The GDT is read-only but the writable GDT is available. */
4438 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4439 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4440 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4441 AssertRCReturn(rc, rc);
4442 }
4443 }
4444
4445 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4446 AssertRC(rc);
4447
4448 /*
4449 * Host FS base and GS base.
4450 */
4451 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4452 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4453 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4454 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4455
4456 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4457 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4458 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4459 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4460 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4461
4462 return VINF_SUCCESS;
4463#undef VMXLOCAL_ADJUST_HOST_SEG
4464}
4465
4466
4467/**
4468 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4469 * host-state area of the VMCS.
4470 *
4471 * These MSRs will be automatically restored on the host after every successful
4472 * VM-exit.
4473 *
4474 * @param pVCpu The cross context virtual CPU structure.
4475 *
4476 * @remarks No-long-jump zone!!!
4477 */
4478static void hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4479{
4480 AssertPtr(pVCpu);
4481
4482 /*
4483 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4484 * rather than swapping them on every VM-entry.
4485 */
4486 hmR0VmxLazySaveHostMsrs(pVCpu);
4487
4488 /*
4489 * Host Sysenter MSRs.
4490 */
4491 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4492 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4493 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4494
4495 /*
4496 * Host EFER MSR.
4497 *
4498 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4499 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4500 */
4501 PVM pVM = pVCpu->CTX_SUFF(pVM);
4502 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4503 {
4504 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4505 AssertRC(rc);
4506 }
4507
4508 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4509 * hmR0VmxExportGuestEntryExitCtls(). */
4510}
4511
4512
4513/**
4514 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4515 *
4516 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4517 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4518 *
4519 * @returns true if we need to load guest EFER, false otherwise.
4520 * @param pVCpu The cross context virtual CPU structure.
4521 *
4522 * @remarks Requires EFER, CR4.
4523 * @remarks No-long-jump zone!!!
4524 */
4525static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4526{
4527#ifdef HMVMX_ALWAYS_SWAP_EFER
4528 RT_NOREF(pVCpu);
4529 return true;
4530#else
4531 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4532 PVM pVM = pVCpu->CTX_SUFF(pVM);
4533 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4534 uint64_t const u64GuestEfer = pCtx->msrEFER;
4535
4536 /*
4537 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4538 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4539 */
4540 if ( CPUMIsGuestInLongModeEx(pCtx)
4541 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4542 return true;
4543
4544 /*
4545 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4546 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4547 *
4548 * See Intel spec. 4.5 "IA-32e Paging".
4549 * See Intel spec. 4.1.1 "Three Paging Modes".
4550 *
4551 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4552 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4553 */
4554 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4555 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4556 if ( (pCtx->cr4 & X86_CR4_PAE)
4557 && (pCtx->cr0 & X86_CR0_PG)
4558 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4559 {
4560 /* Assert that host is NX capable. */
4561 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4562 return true;
4563 }
4564
4565 return false;
4566#endif
4567}
4568
4569/**
4570 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4571 * VMCS.
4572 *
4573 * This is typically required when the guest changes paging mode.
4574 *
4575 * @returns VBox status code.
4576 * @param pVCpu The cross context virtual CPU structure.
4577 * @param pVmxTransient The VMX-transient structure.
4578 *
4579 * @remarks Requires EFER.
4580 * @remarks No-long-jump zone!!!
4581 */
4582static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4583{
4584 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4585 {
4586 PVM pVM = pVCpu->CTX_SUFF(pVM);
4587 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4588
4589 /*
4590 * VM-entry controls.
4591 */
4592 {
4593 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4594 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4595
4596 /*
4597 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4598 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4599 *
4600 * For nested-guests, this is a mandatory VM-entry control. It's also
4601 * required because we do not want to leak host bits to the nested-guest.
4602 */
4603 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4604
4605 /*
4606 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4607 *
4608 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4609 * required to get the nested-guest working with hardware-assisted VMX execution.
4610 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4611 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4612 * here rather than while merging the guest VMCS controls.
4613 */
4614 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4615 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4616 else
4617 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4618
4619 /*
4620 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4621 *
4622 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4623 * regardless of whether the nested-guest VMCS specifies it because we are free to
4624 * load whatever MSRs we require and we do not need to modify the guest visible copy
4625 * of the VM-entry MSR load area.
4626 */
4627 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4628 && hmR0VmxShouldSwapEferMsr(pVCpu))
4629 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4630 else
4631 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4632
4633 /*
4634 * The following should -not- be set (since we're not in SMM mode):
4635 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4636 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4637 */
4638
4639 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4640 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4641
4642 if ((fVal & fZap) == fVal)
4643 { /* likely */ }
4644 else
4645 {
4646 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4647 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4648 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4649 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4650 }
4651
4652 /* Commit it to the VMCS. */
4653 if (pVmcsInfo->u32EntryCtls != fVal)
4654 {
4655 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4656 AssertRC(rc);
4657 pVmcsInfo->u32EntryCtls = fVal;
4658 }
4659 }
4660
4661 /*
4662 * VM-exit controls.
4663 */
4664 {
4665 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4666 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4667
4668 /*
4669 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4670 * supported the 1-setting of this bit.
4671 *
4672 * For nested-guests, we set the "save debug controls" as the converse
4673 * "load debug controls" is mandatory for nested-guests anyway.
4674 */
4675 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4676
4677 /*
4678 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4679 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4680 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4681 * hmR0VmxExportHostMsrs().
4682 *
4683 * For nested-guests, we always set this bit as we do not support 32-bit
4684 * hosts.
4685 */
4686 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4687
4688 /*
4689 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4690 *
4691 * For nested-guests, we should use the "save IA32_EFER" control if we also
4692 * used the "load IA32_EFER" control while exporting VM-entry controls.
4693 */
4694 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4695 && hmR0VmxShouldSwapEferMsr(pVCpu))
4696 {
4697 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4698 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4699 }
4700
4701 /*
4702 * Enable saving of the VMX-preemption timer value on VM-exit.
4703 * For nested-guests, currently not exposed/used.
4704 */
4705 if ( pVM->hm.s.vmx.fUsePreemptTimer
4706 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4707 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4708
4709 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4710 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4711
4712 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4713 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4714 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4715
4716 if ((fVal & fZap) == fVal)
4717 { /* likely */ }
4718 else
4719 {
4720 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4721 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4722 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4723 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4724 }
4725
4726 /* Commit it to the VMCS. */
4727 if (pVmcsInfo->u32ExitCtls != fVal)
4728 {
4729 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4730 AssertRC(rc);
4731 pVmcsInfo->u32ExitCtls = fVal;
4732 }
4733 }
4734
4735 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4736 }
4737 return VINF_SUCCESS;
4738}
4739
4740
4741/**
4742 * Sets the TPR threshold in the VMCS.
4743 *
4744 * @param pVmcsInfo The VMCS info. object.
4745 * @param u32TprThreshold The TPR threshold (task-priority class only).
4746 */
4747DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4748{
4749 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4750 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4751 RT_NOREF(pVmcsInfo);
4752 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4753 AssertRC(rc);
4754}
4755
4756
4757/**
4758 * Exports the guest APIC TPR state into the VMCS.
4759 *
4760 * @returns VBox status code.
4761 * @param pVCpu The cross context virtual CPU structure.
4762 * @param pVmxTransient The VMX-transient structure.
4763 *
4764 * @remarks No-long-jump zone!!!
4765 */
4766static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4767{
4768 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4769 {
4770 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4771
4772 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4773 if (!pVmxTransient->fIsNestedGuest)
4774 {
4775 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4776 && APICIsEnabled(pVCpu))
4777 {
4778 /*
4779 * Setup TPR shadowing.
4780 */
4781 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4782 {
4783 bool fPendingIntr = false;
4784 uint8_t u8Tpr = 0;
4785 uint8_t u8PendingIntr = 0;
4786 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4787 AssertRCReturn(rc, rc);
4788
4789 /*
4790 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4791 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4792 * priority of the pending interrupt so we can deliver the interrupt. If there
4793 * are no interrupts pending, set threshold to 0 to not cause any
4794 * TPR-below-threshold VM-exits.
4795 */
4796 uint32_t u32TprThreshold = 0;
4797 if (fPendingIntr)
4798 {
4799 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4800 (which is the Task-Priority Class). */
4801 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4802 const uint8_t u8TprPriority = u8Tpr >> 4;
4803 if (u8PendingPriority <= u8TprPriority)
4804 u32TprThreshold = u8PendingPriority;
4805 }
4806
4807 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4808 }
4809 }
4810 }
4811 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4812 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4813 }
4814 return VINF_SUCCESS;
4815}
4816
4817
4818/**
4819 * Gets the guest interruptibility-state.
4820 *
4821 * @returns Guest's interruptibility-state.
4822 * @param pVCpu The cross context virtual CPU structure.
4823 * @param pVmxTransient The VMX-transient structure.
4824 *
4825 * @remarks No-long-jump zone!!!
4826 */
4827static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4828{
4829 /*
4830 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4831 */
4832 uint32_t fIntrState = 0;
4833 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4834 {
4835 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4836 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4837
4838 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4839 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4840 {
4841 if (pCtx->eflags.Bits.u1IF)
4842 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4843 else
4844 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4845 }
4846 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4847 {
4848 /*
4849 * We can clear the inhibit force flag as even if we go back to the recompiler
4850 * without executing guest code in VT-x, the flag's condition to be cleared is
4851 * met and thus the cleared state is correct.
4852 */
4853 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4854 }
4855 }
4856
4857 /*
4858 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4859 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4860 * setting this would block host-NMIs and IRET will not clear the blocking.
4861 *
4862 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4863 *
4864 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4865 */
4866 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4867 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4868 && CPUMIsGuestNmiBlocking(pVCpu))
4869 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4870
4871 return fIntrState;
4872}
4873
4874
4875/**
4876 * Exports the exception intercepts required for guest execution in the VMCS.
4877 *
4878 * @returns VBox status code.
4879 * @param pVCpu The cross context virtual CPU structure.
4880 * @param pVmxTransient The VMX-transient structure.
4881 *
4882 * @remarks No-long-jump zone!!!
4883 */
4884static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4885{
4886 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4887 {
4888 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4889 if ( !pVmxTransient->fIsNestedGuest
4890 && pVCpu->hm.s.fGIMTrapXcptUD)
4891 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4892 else
4893 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4894
4895 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
4896 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
4897 }
4898 return VINF_SUCCESS;
4899}
4900
4901
4902/**
4903 * Exports the guest's RIP into the guest-state area in the VMCS.
4904 *
4905 * @returns VBox status code.
4906 * @param pVCpu The cross context virtual CPU structure.
4907 *
4908 * @remarks No-long-jump zone!!!
4909 */
4910static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
4911{
4912 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
4913 {
4914 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
4915
4916 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
4917 AssertRC(rc);
4918
4919 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
4920 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
4921 }
4922 return VINF_SUCCESS;
4923}
4924
4925
4926/**
4927 * Exports the guest's RSP into the guest-state area in the VMCS.
4928 *
4929 * @returns VBox status code.
4930 * @param pVCpu The cross context virtual CPU structure.
4931 *
4932 * @remarks No-long-jump zone!!!
4933 */
4934static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
4935{
4936 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
4937 {
4938 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
4939
4940 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
4941 AssertRC(rc);
4942
4943 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
4944 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
4945 }
4946 return VINF_SUCCESS;
4947}
4948
4949
4950/**
4951 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
4952 *
4953 * @returns VBox status code.
4954 * @param pVCpu The cross context virtual CPU structure.
4955 * @param pVmxTransient The VMX-transient structure.
4956 *
4957 * @remarks No-long-jump zone!!!
4958 */
4959static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4960{
4961 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
4962 {
4963 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
4964
4965 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
4966 Let us assert it as such and use 32-bit VMWRITE. */
4967 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
4968 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
4969 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
4970 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
4971
4972 /*
4973 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
4974 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
4975 * can run the real-mode guest code under Virtual 8086 mode.
4976 */
4977 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4978 if (pVmcsInfo->RealMode.fRealOnV86Active)
4979 {
4980 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
4981 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
4982 Assert(!pVmxTransient->fIsNestedGuest);
4983 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
4984 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
4985 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
4986 }
4987
4988 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
4989 AssertRC(rc);
4990
4991 /*
4992 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
4993 *
4994 * We must avoid setting any automatic debug exceptions delivery when single-stepping
4995 * through the hypervisor debugger using EFLAGS.TF.
4996 */
4997 if ( !pVmxTransient->fIsNestedGuest
4998 && !pVCpu->hm.s.fSingleInstruction
4999 && fEFlags.Bits.u1TF)
5000 {
5001 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5002 * premature trips to ring-3 esp since IEM does not yet handle it. */
5003 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5004 AssertRC(rc);
5005 }
5006 /* else: for nested-guest currently handling while merging controls. */
5007
5008 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5009 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5010 }
5011 return VINF_SUCCESS;
5012}
5013
5014
5015#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5016/**
5017 * Copies the nested-guest VMCS to the shadow VMCS.
5018 *
5019 * @returns VBox status code.
5020 * @param pVCpu The cross context virtual CPU structure.
5021 * @param pVmcsInfo The VMCS info. object.
5022 *
5023 * @remarks No-long-jump zone!!!
5024 */
5025static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5026{
5027 PVM pVM = pVCpu->CTX_SUFF(pVM);
5028 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5029
5030 /*
5031 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5032 * current VMCS, as we may try saving guest lazy MSRs.
5033 *
5034 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5035 * calling the import VMCS code which is currently performing the guest MSR reads
5036 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5037 * and the rest of the VMX leave session machinery.
5038 */
5039 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5040
5041 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5042 if (RT_SUCCESS(rc))
5043 {
5044 /*
5045 * Copy all guest read/write VMCS fields.
5046 *
5047 * We don't check for VMWRITE failures here for performance reasons and
5048 * because they are not expected to fail, barring irrecoverable conditions
5049 * like hardware errors.
5050 */
5051 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5052 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5053 {
5054 uint64_t u64Val;
5055 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5056 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5057 VMXWriteVmcs64(uVmcsField, u64Val);
5058 }
5059
5060 /*
5061 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5062 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5063 */
5064 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5065 {
5066 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5067 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5068 {
5069 uint64_t u64Val;
5070 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5071 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5072 VMXWriteVmcs64(uVmcsField, u64Val);
5073 }
5074 }
5075
5076 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5077 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5078 }
5079
5080 ASMSetFlags(fEFlags);
5081 return rc;
5082}
5083
5084
5085/**
5086 * Copies the shadow VMCS to the nested-guest VMCS.
5087 *
5088 * @returns VBox status code.
5089 * @param pVCpu The cross context virtual CPU structure.
5090 * @param pVmcsInfo The VMCS info. object.
5091 *
5092 * @remarks Called with interrupts disabled.
5093 */
5094static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5095{
5096 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5097 PVM pVM = pVCpu->CTX_SUFF(pVM);
5098 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5099
5100 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5101 if (RT_SUCCESS(rc))
5102 {
5103 /*
5104 * Copy guest read/write fields from the shadow VMCS.
5105 * Guest read-only fields cannot be modified, so no need to copy them.
5106 *
5107 * We don't check for VMREAD failures here for performance reasons and
5108 * because they are not expected to fail, barring irrecoverable conditions
5109 * like hardware errors.
5110 */
5111 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5112 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5113 {
5114 uint64_t u64Val;
5115 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5116 VMXReadVmcs64(uVmcsField, &u64Val);
5117 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5118 }
5119
5120 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5121 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5122 }
5123 return rc;
5124}
5125
5126
5127/**
5128 * Enables VMCS shadowing for the given VMCS info. object.
5129 *
5130 * @param pVmcsInfo The VMCS info. object.
5131 *
5132 * @remarks No-long-jump zone!!!
5133 */
5134static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5135{
5136 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5137 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5138 {
5139 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5140 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5141 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5142 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5143 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5144 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5145 Log4Func(("Enabled\n"));
5146 }
5147}
5148
5149
5150/**
5151 * Disables VMCS shadowing for the given VMCS info. object.
5152 *
5153 * @param pVmcsInfo The VMCS info. object.
5154 *
5155 * @remarks No-long-jump zone!!!
5156 */
5157static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5158{
5159 /*
5160 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5161 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5162 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5163 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5164 *
5165 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5166 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5167 */
5168 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5169 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5170 {
5171 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5172 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5173 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5174 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5175 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5176 Log4Func(("Disabled\n"));
5177 }
5178}
5179#endif
5180
5181
5182/**
5183 * Exports the guest hardware-virtualization state.
5184 *
5185 * @returns VBox status code.
5186 * @param pVCpu The cross context virtual CPU structure.
5187 * @param pVmxTransient The VMX-transient structure.
5188 *
5189 * @remarks No-long-jump zone!!!
5190 */
5191static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5192{
5193 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5194 {
5195#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5196 /*
5197 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5198 * VMCS shadowing.
5199 */
5200 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5201 {
5202 /*
5203 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5204 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5205 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5206 *
5207 * We check for VMX root mode here in case the guest executes VMXOFF without
5208 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5209 * not clear the current VMCS pointer.
5210 */
5211 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5212 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5213 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5214 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5215 {
5216 /* Paranoia. */
5217 Assert(!pVmxTransient->fIsNestedGuest);
5218
5219 /*
5220 * For performance reasons, also check if the guest hypervisor's current VMCS
5221 * was newly loaded or modified before copying it to the shadow VMCS.
5222 */
5223 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5224 {
5225 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5226 AssertRCReturn(rc, rc);
5227 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5228 }
5229 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5230 }
5231 else
5232 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5233 }
5234#else
5235 NOREF(pVmxTransient);
5236#endif
5237 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5238 }
5239 return VINF_SUCCESS;
5240}
5241
5242
5243/**
5244 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5245 *
5246 * The guest FPU state is always pre-loaded hence we don't need to bother about
5247 * sharing FPU related CR0 bits between the guest and host.
5248 *
5249 * @returns VBox status code.
5250 * @param pVCpu The cross context virtual CPU structure.
5251 * @param pVmxTransient The VMX-transient structure.
5252 *
5253 * @remarks No-long-jump zone!!!
5254 */
5255static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5256{
5257 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5258 {
5259 PVM pVM = pVCpu->CTX_SUFF(pVM);
5260 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5261
5262 /*
5263 * Figure out fixed CR0 bits in VMX operation.
5264 */
5265 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5266 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5267 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5268 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5269 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5270 else
5271 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5272
5273 if (!pVmxTransient->fIsNestedGuest)
5274 {
5275 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5276 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5277 uint64_t const u64ShadowCr0 = u64GuestCr0;
5278 Assert(!RT_HI_U32(u64GuestCr0));
5279
5280 /*
5281 * Setup VT-x's view of the guest CR0.
5282 */
5283 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5284 if (pVM->hm.s.fNestedPaging)
5285 {
5286 if (CPUMIsGuestPagingEnabled(pVCpu))
5287 {
5288 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5289 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5290 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5291 }
5292 else
5293 {
5294 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5295 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5296 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5297 }
5298
5299 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5300 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5301 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5302 }
5303 else
5304 {
5305 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5306 u64GuestCr0 |= X86_CR0_WP;
5307 }
5308
5309 /*
5310 * Guest FPU bits.
5311 *
5312 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5313 * using CR0.TS.
5314 *
5315 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5316 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5317 */
5318 u64GuestCr0 |= X86_CR0_NE;
5319
5320 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5321 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5322
5323 /*
5324 * Update exception intercepts.
5325 */
5326 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5327 if (pVmcsInfo->RealMode.fRealOnV86Active)
5328 {
5329 Assert(PDMVmmDevHeapIsEnabled(pVM));
5330 Assert(pVM->hm.s.vmx.pRealModeTSS);
5331 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5332 }
5333 else
5334 {
5335 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5336 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5337 if (fInterceptMF)
5338 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5339 }
5340
5341 /* Additional intercepts for debugging, define these yourself explicitly. */
5342#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5343 uXcptBitmap |= 0
5344 | RT_BIT(X86_XCPT_BP)
5345 | RT_BIT(X86_XCPT_DE)
5346 | RT_BIT(X86_XCPT_NM)
5347 | RT_BIT(X86_XCPT_TS)
5348 | RT_BIT(X86_XCPT_UD)
5349 | RT_BIT(X86_XCPT_NP)
5350 | RT_BIT(X86_XCPT_SS)
5351 | RT_BIT(X86_XCPT_GP)
5352 | RT_BIT(X86_XCPT_PF)
5353 | RT_BIT(X86_XCPT_MF)
5354 ;
5355#elif defined(HMVMX_ALWAYS_TRAP_PF)
5356 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5357#endif
5358 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5359 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5360 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5361
5362 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5363 u64GuestCr0 |= fSetCr0;
5364 u64GuestCr0 &= fZapCr0;
5365 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5366
5367 /* Commit the CR0 and related fields to the guest VMCS. */
5368 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5369 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5370 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5371 {
5372 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5373 AssertRC(rc);
5374 }
5375 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5376 {
5377 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5378 AssertRC(rc);
5379 }
5380
5381 /* Update our caches. */
5382 pVmcsInfo->u32ProcCtls = uProcCtls;
5383 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5384
5385 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5386 }
5387 else
5388 {
5389 /*
5390 * With nested-guests, we may have extended the guest/host mask here since we
5391 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5392 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5393 * originally supplied. We must copy those bits from the nested-guest CR0 into
5394 * the nested-guest CR0 read-shadow.
5395 */
5396 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5397 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5398 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5399 Assert(!RT_HI_U32(u64GuestCr0));
5400 Assert(u64GuestCr0 & X86_CR0_NE);
5401
5402 /*
5403 * Apply the hardware specified fixed CR0 bits and enable caching.
5404 * Note! We could be altering our VMX emulation's fixed bits. We thus
5405 * need to re-apply them while importing CR0.
5406 */
5407 u64GuestCr0 |= fSetCr0;
5408 u64GuestCr0 &= fZapCr0;
5409 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5410
5411 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5412 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5413 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5414
5415 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5416 }
5417
5418 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5419 }
5420
5421 return VINF_SUCCESS;
5422}
5423
5424
5425/**
5426 * Exports the guest control registers (CR3, CR4) into the guest-state area
5427 * in the VMCS.
5428 *
5429 * @returns VBox strict status code.
5430 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5431 * without unrestricted guest access and the VMMDev is not presently
5432 * mapped (e.g. EFI32).
5433 *
5434 * @param pVCpu The cross context virtual CPU structure.
5435 * @param pVmxTransient The VMX-transient structure.
5436 *
5437 * @remarks No-long-jump zone!!!
5438 */
5439static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5440{
5441 int rc = VINF_SUCCESS;
5442 PVM pVM = pVCpu->CTX_SUFF(pVM);
5443
5444 /*
5445 * Guest CR2.
5446 * It's always loaded in the assembler code. Nothing to do here.
5447 */
5448
5449 /*
5450 * Guest CR3.
5451 */
5452 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5453 {
5454 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5455
5456 if (pVM->hm.s.fNestedPaging)
5457 {
5458 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5459 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5460
5461 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5462 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5463 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5464 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5465
5466 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5467 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5468 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5469
5470 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5471 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5472 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5473 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5474 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5475 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5476 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5477
5478 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5479 AssertRC(rc);
5480
5481 uint64_t u64GuestCr3;
5482 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5483 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5484 || CPUMIsGuestPagingEnabledEx(pCtx))
5485 {
5486 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5487 if (CPUMIsGuestInPAEModeEx(pCtx))
5488 {
5489 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5490 AssertRC(rc);
5491 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5492 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5493 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5494 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5495 }
5496
5497 /*
5498 * The guest's view of its CR3 is unblemished with nested paging when the
5499 * guest is using paging or we have unrestricted guest execution to handle
5500 * the guest when it's not using paging.
5501 */
5502 u64GuestCr3 = pCtx->cr3;
5503 }
5504 else
5505 {
5506 /*
5507 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5508 * thinks it accesses physical memory directly, we use our identity-mapped
5509 * page table to map guest-linear to guest-physical addresses. EPT takes care
5510 * of translating it to host-physical addresses.
5511 */
5512 RTGCPHYS GCPhys;
5513 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5514
5515 /* We obtain it here every time as the guest could have relocated this PCI region. */
5516 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5517 if (RT_SUCCESS(rc))
5518 { /* likely */ }
5519 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5520 {
5521 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5522 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5523 }
5524 else
5525 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5526
5527 u64GuestCr3 = GCPhys;
5528 }
5529
5530 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5531 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5532 AssertRC(rc);
5533 }
5534 else
5535 {
5536 /* Non-nested paging case, just use the hypervisor's CR3. */
5537 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5538
5539 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5540 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5541 AssertRC(rc);
5542 }
5543
5544 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5545 }
5546
5547 /*
5548 * Guest CR4.
5549 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5550 */
5551 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5552 {
5553 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5554 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5555
5556 /*
5557 * Figure out fixed CR4 bits in VMX operation.
5558 */
5559 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5560 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5561 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5562
5563 /*
5564 * With nested-guests, we may have extended the guest/host mask here (since we
5565 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5566 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5567 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5568 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5569 */
5570 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5571 uint64_t u64GuestCr4 = pCtx->cr4;
5572 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5573 ? pCtx->cr4
5574 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5575 Assert(!RT_HI_U32(u64GuestCr4));
5576
5577 /*
5578 * Setup VT-x's view of the guest CR4.
5579 *
5580 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5581 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5582 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5583 *
5584 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5585 */
5586 if (pVmcsInfo->RealMode.fRealOnV86Active)
5587 {
5588 Assert(pVM->hm.s.vmx.pRealModeTSS);
5589 Assert(PDMVmmDevHeapIsEnabled(pVM));
5590 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5591 }
5592
5593 if (pVM->hm.s.fNestedPaging)
5594 {
5595 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5596 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5597 {
5598 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5599 u64GuestCr4 |= X86_CR4_PSE;
5600 /* Our identity mapping is a 32-bit page directory. */
5601 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5602 }
5603 /* else use guest CR4.*/
5604 }
5605 else
5606 {
5607 Assert(!pVmxTransient->fIsNestedGuest);
5608
5609 /*
5610 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5611 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5612 */
5613 switch (pVCpu->hm.s.enmShadowMode)
5614 {
5615 case PGMMODE_REAL: /* Real-mode. */
5616 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5617 case PGMMODE_32_BIT: /* 32-bit paging. */
5618 {
5619 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5620 break;
5621 }
5622
5623 case PGMMODE_PAE: /* PAE paging. */
5624 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5625 {
5626 u64GuestCr4 |= X86_CR4_PAE;
5627 break;
5628 }
5629
5630 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5631 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5632#ifdef VBOX_WITH_64_BITS_GUESTS
5633 break;
5634#endif
5635 default:
5636 AssertFailed();
5637 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5638 }
5639 }
5640
5641 /*
5642 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
5643 * Note! For nested-guests, we could be altering our VMX emulation's
5644 * fixed bits. We thus need to re-apply them while importing CR4.
5645 */
5646 u64GuestCr4 |= fSetCr4;
5647 u64GuestCr4 &= fZapCr4;
5648
5649 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5650 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5651 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5652
5653 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5654 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5655
5656 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5657
5658 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5659 }
5660 return rc;
5661}
5662
5663
5664/**
5665 * Exports the guest debug registers into the guest-state area in the VMCS.
5666 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5667 *
5668 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5669 *
5670 * @returns VBox status code.
5671 * @param pVCpu The cross context virtual CPU structure.
5672 * @param pVmxTransient The VMX-transient structure.
5673 *
5674 * @remarks No-long-jump zone!!!
5675 */
5676static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5677{
5678 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5679
5680 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5681 * stepping. */
5682 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5683 if (pVmxTransient->fIsNestedGuest)
5684 {
5685 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5686 AssertRC(rc);
5687
5688 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5689 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5690 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5691 AssertRC(rc);
5692 return VINF_SUCCESS;
5693 }
5694
5695#ifdef VBOX_STRICT
5696 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5697 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5698 {
5699 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5700 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5701 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5702 }
5703#endif
5704
5705 bool fSteppingDB = false;
5706 bool fInterceptMovDRx = false;
5707 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5708 if (pVCpu->hm.s.fSingleInstruction)
5709 {
5710 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5711 PVM pVM = pVCpu->CTX_SUFF(pVM);
5712 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5713 {
5714 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5715 Assert(fSteppingDB == false);
5716 }
5717 else
5718 {
5719 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5720 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5721 pVCpu->hm.s.fClearTrapFlag = true;
5722 fSteppingDB = true;
5723 }
5724 }
5725
5726 uint64_t u64GuestDr7;
5727 if ( fSteppingDB
5728 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5729 {
5730 /*
5731 * Use the combined guest and host DRx values found in the hypervisor register set
5732 * because the hypervisor debugger has breakpoints active or someone is single stepping
5733 * on the host side without a monitor trap flag.
5734 *
5735 * Note! DBGF expects a clean DR6 state before executing guest code.
5736 */
5737 if (!CPUMIsHyperDebugStateActive(pVCpu))
5738 {
5739 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5740 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5741 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5742 }
5743
5744 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5745 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5746 pVCpu->hm.s.fUsingHyperDR7 = true;
5747 fInterceptMovDRx = true;
5748 }
5749 else
5750 {
5751 /*
5752 * If the guest has enabled debug registers, we need to load them prior to
5753 * executing guest code so they'll trigger at the right time.
5754 */
5755 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5756 {
5757 if (!CPUMIsGuestDebugStateActive(pVCpu))
5758 {
5759 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5760 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5761 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5762 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5763 }
5764 Assert(!fInterceptMovDRx);
5765 }
5766 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5767 {
5768 /*
5769 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5770 * must intercept #DB in order to maintain a correct DR6 guest value, and
5771 * because we need to intercept it to prevent nested #DBs from hanging the
5772 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5773 */
5774 fInterceptMovDRx = true;
5775 }
5776
5777 /* Update DR7 with the actual guest value. */
5778 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5779 pVCpu->hm.s.fUsingHyperDR7 = false;
5780 }
5781
5782 if (fInterceptMovDRx)
5783 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5784 else
5785 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5786
5787 /*
5788 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5789 * monitor-trap flag and update our cache.
5790 */
5791 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5792 {
5793 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5794 AssertRC(rc);
5795 pVmcsInfo->u32ProcCtls = uProcCtls;
5796 }
5797
5798 /*
5799 * Update guest DR7.
5800 */
5801 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5802 AssertRC(rc);
5803
5804 /*
5805 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5806 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5807 *
5808 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5809 */
5810 if (fSteppingDB)
5811 {
5812 Assert(pVCpu->hm.s.fSingleInstruction);
5813 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5814
5815 uint32_t fIntrState = 0;
5816 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5817 AssertRC(rc);
5818
5819 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5820 {
5821 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5822 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5823 AssertRC(rc);
5824 }
5825 }
5826
5827 return VINF_SUCCESS;
5828}
5829
5830
5831#ifdef VBOX_STRICT
5832/**
5833 * Strict function to validate segment registers.
5834 *
5835 * @param pVCpu The cross context virtual CPU structure.
5836 * @param pVmcsInfo The VMCS info. object.
5837 *
5838 * @remarks Will import guest CR0 on strict builds during validation of
5839 * segments.
5840 */
5841static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5842{
5843 /*
5844 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5845 *
5846 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5847 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5848 * unusable bit and doesn't change the guest-context value.
5849 */
5850 PVM pVM = pVCpu->CTX_SUFF(pVM);
5851 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5852 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5853 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5854 && ( !CPUMIsGuestInRealModeEx(pCtx)
5855 && !CPUMIsGuestInV86ModeEx(pCtx)))
5856 {
5857 /* Protected mode checks */
5858 /* CS */
5859 Assert(pCtx->cs.Attr.n.u1Present);
5860 Assert(!(pCtx->cs.Attr.u & 0xf00));
5861 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5862 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5863 || !(pCtx->cs.Attr.n.u1Granularity));
5864 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5865 || (pCtx->cs.Attr.n.u1Granularity));
5866 /* CS cannot be loaded with NULL in protected mode. */
5867 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5868 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5869 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5870 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5871 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5872 else
5873 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5874 /* SS */
5875 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5876 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5877 if ( !(pCtx->cr0 & X86_CR0_PE)
5878 || pCtx->cs.Attr.n.u4Type == 3)
5879 {
5880 Assert(!pCtx->ss.Attr.n.u2Dpl);
5881 }
5882 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5883 {
5884 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5885 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5886 Assert(pCtx->ss.Attr.n.u1Present);
5887 Assert(!(pCtx->ss.Attr.u & 0xf00));
5888 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5889 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5890 || !(pCtx->ss.Attr.n.u1Granularity));
5891 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5892 || (pCtx->ss.Attr.n.u1Granularity));
5893 }
5894 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5895 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5896 {
5897 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5898 Assert(pCtx->ds.Attr.n.u1Present);
5899 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5900 Assert(!(pCtx->ds.Attr.u & 0xf00));
5901 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5902 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5903 || !(pCtx->ds.Attr.n.u1Granularity));
5904 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5905 || (pCtx->ds.Attr.n.u1Granularity));
5906 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5907 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5908 }
5909 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5910 {
5911 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5912 Assert(pCtx->es.Attr.n.u1Present);
5913 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
5914 Assert(!(pCtx->es.Attr.u & 0xf00));
5915 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
5916 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
5917 || !(pCtx->es.Attr.n.u1Granularity));
5918 Assert( !(pCtx->es.u32Limit & 0xfff00000)
5919 || (pCtx->es.Attr.n.u1Granularity));
5920 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5921 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
5922 }
5923 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
5924 {
5925 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5926 Assert(pCtx->fs.Attr.n.u1Present);
5927 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
5928 Assert(!(pCtx->fs.Attr.u & 0xf00));
5929 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
5930 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
5931 || !(pCtx->fs.Attr.n.u1Granularity));
5932 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
5933 || (pCtx->fs.Attr.n.u1Granularity));
5934 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5935 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5936 }
5937 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
5938 {
5939 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5940 Assert(pCtx->gs.Attr.n.u1Present);
5941 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
5942 Assert(!(pCtx->gs.Attr.u & 0xf00));
5943 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
5944 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
5945 || !(pCtx->gs.Attr.n.u1Granularity));
5946 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
5947 || (pCtx->gs.Attr.n.u1Granularity));
5948 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5949 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
5950 }
5951 /* 64-bit capable CPUs. */
5952 Assert(!RT_HI_U32(pCtx->cs.u64Base));
5953 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
5954 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
5955 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
5956 }
5957 else if ( CPUMIsGuestInV86ModeEx(pCtx)
5958 || ( CPUMIsGuestInRealModeEx(pCtx)
5959 && !pVM->hm.s.vmx.fUnrestrictedGuest))
5960 {
5961 /* Real and v86 mode checks. */
5962 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
5963 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
5964 if (pVmcsInfo->RealMode.fRealOnV86Active)
5965 {
5966 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
5967 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
5968 }
5969 else
5970 {
5971 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
5972 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
5973 }
5974
5975 /* CS */
5976 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
5977 Assert(pCtx->cs.u32Limit == 0xffff);
5978 Assert(u32CSAttr == 0xf3);
5979 /* SS */
5980 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
5981 Assert(pCtx->ss.u32Limit == 0xffff);
5982 Assert(u32SSAttr == 0xf3);
5983 /* DS */
5984 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
5985 Assert(pCtx->ds.u32Limit == 0xffff);
5986 Assert(u32DSAttr == 0xf3);
5987 /* ES */
5988 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
5989 Assert(pCtx->es.u32Limit == 0xffff);
5990 Assert(u32ESAttr == 0xf3);
5991 /* FS */
5992 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
5993 Assert(pCtx->fs.u32Limit == 0xffff);
5994 Assert(u32FSAttr == 0xf3);
5995 /* GS */
5996 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
5997 Assert(pCtx->gs.u32Limit == 0xffff);
5998 Assert(u32GSAttr == 0xf3);
5999 /* 64-bit capable CPUs. */
6000 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6001 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6002 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6003 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6004 }
6005}
6006#endif /* VBOX_STRICT */
6007
6008
6009/**
6010 * Exports a guest segment register into the guest-state area in the VMCS.
6011 *
6012 * @returns VBox status code.
6013 * @param pVCpu The cross context virtual CPU structure.
6014 * @param pVmcsInfo The VMCS info. object.
6015 * @param iSegReg The segment register number (X86_SREG_XXX).
6016 * @param pSelReg Pointer to the segment selector.
6017 *
6018 * @remarks No-long-jump zone!!!
6019 */
6020static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6021{
6022 Assert(iSegReg < X86_SREG_COUNT);
6023 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6024 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6025 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6026 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6027
6028 uint32_t u32Access = pSelReg->Attr.u;
6029 if (pVmcsInfo->RealMode.fRealOnV86Active)
6030 {
6031 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6032 u32Access = 0xf3;
6033 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6034 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6035 RT_NOREF_PV(pVCpu);
6036 }
6037 else
6038 {
6039 /*
6040 * The way to differentiate between whether this is really a null selector or was just
6041 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6042 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6043 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6044 * NULL selectors loaded in protected-mode have their attribute as 0.
6045 */
6046 if (!u32Access)
6047 u32Access = X86DESCATTR_UNUSABLE;
6048 }
6049
6050 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6051 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6052 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6053
6054 /*
6055 * Commit it to the VMCS.
6056 */
6057 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6058 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6059 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6060 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6061 return VINF_SUCCESS;
6062}
6063
6064
6065/**
6066 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6067 * area in the VMCS.
6068 *
6069 * @returns VBox status code.
6070 * @param pVCpu The cross context virtual CPU structure.
6071 * @param pVmxTransient The VMX-transient structure.
6072 *
6073 * @remarks Will import guest CR0 on strict builds during validation of
6074 * segments.
6075 * @remarks No-long-jump zone!!!
6076 */
6077static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6078{
6079 int rc = VERR_INTERNAL_ERROR_5;
6080 PVM pVM = pVCpu->CTX_SUFF(pVM);
6081 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6082 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6083
6084 /*
6085 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6086 */
6087 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6088 {
6089#ifdef VBOX_WITH_REM
6090 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6091 {
6092 Assert(!pVmxTransient->fIsNestedGuest);
6093 Assert(pVM->hm.s.vmx.pRealModeTSS);
6094 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6095 if ( pVmcsInfo->fWasInRealMode
6096 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6097 {
6098 /*
6099 * Notify the recompiler must flush its code-cache as the guest -may-
6100 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6101 */
6102 REMFlushTBs(pVM);
6103 Log4Func(("Switch to protected mode detected!\n"));
6104 pVmcsInfo->fWasInRealMode = false;
6105 }
6106 }
6107#endif
6108 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6109 {
6110 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6111 if (pVmcsInfo->RealMode.fRealOnV86Active)
6112 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6113 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6114 AssertRC(rc);
6115 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6116 }
6117
6118 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6119 {
6120 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6121 if (pVmcsInfo->RealMode.fRealOnV86Active)
6122 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6123 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6124 AssertRC(rc);
6125 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6126 }
6127
6128 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6129 {
6130 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6131 if (pVmcsInfo->RealMode.fRealOnV86Active)
6132 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6133 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6134 AssertRC(rc);
6135 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6136 }
6137
6138 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6139 {
6140 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6141 if (pVmcsInfo->RealMode.fRealOnV86Active)
6142 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6143 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6144 AssertRC(rc);
6145 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6146 }
6147
6148 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6149 {
6150 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6151 if (pVmcsInfo->RealMode.fRealOnV86Active)
6152 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6153 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6154 AssertRC(rc);
6155 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6156 }
6157
6158 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6159 {
6160 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6161 if (pVmcsInfo->RealMode.fRealOnV86Active)
6162 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6163 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6164 AssertRC(rc);
6165 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6166 }
6167
6168#ifdef VBOX_STRICT
6169 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6170#endif
6171 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6172 pCtx->cs.Attr.u));
6173 }
6174
6175 /*
6176 * Guest TR.
6177 */
6178 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6179 {
6180 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6181
6182 /*
6183 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6184 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6185 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6186 */
6187 uint16_t u16Sel;
6188 uint32_t u32Limit;
6189 uint64_t u64Base;
6190 uint32_t u32AccessRights;
6191 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6192 {
6193 u16Sel = pCtx->tr.Sel;
6194 u32Limit = pCtx->tr.u32Limit;
6195 u64Base = pCtx->tr.u64Base;
6196 u32AccessRights = pCtx->tr.Attr.u;
6197 }
6198 else
6199 {
6200 Assert(!pVmxTransient->fIsNestedGuest);
6201 Assert(pVM->hm.s.vmx.pRealModeTSS);
6202 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6203
6204 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6205 RTGCPHYS GCPhys;
6206 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6207 AssertRCReturn(rc, rc);
6208
6209 X86DESCATTR DescAttr;
6210 DescAttr.u = 0;
6211 DescAttr.n.u1Present = 1;
6212 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6213
6214 u16Sel = 0;
6215 u32Limit = HM_VTX_TSS_SIZE;
6216 u64Base = GCPhys;
6217 u32AccessRights = DescAttr.u;
6218 }
6219
6220 /* Validate. */
6221 Assert(!(u16Sel & RT_BIT(2)));
6222 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6223 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6224 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6225 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6226 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6227 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6228 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6229 Assert( (u32Limit & 0xfff) == 0xfff
6230 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6231 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6232 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6233
6234 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6235 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6236 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6237 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6238
6239 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6240 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6241 }
6242
6243 /*
6244 * Guest GDTR.
6245 */
6246 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6247 {
6248 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6249
6250 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6251 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6252
6253 /* Validate. */
6254 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6255
6256 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6257 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6258 }
6259
6260 /*
6261 * Guest LDTR.
6262 */
6263 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6264 {
6265 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6266
6267 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6268 uint32_t u32Access;
6269 if ( !pVmxTransient->fIsNestedGuest
6270 && !pCtx->ldtr.Attr.u)
6271 u32Access = X86DESCATTR_UNUSABLE;
6272 else
6273 u32Access = pCtx->ldtr.Attr.u;
6274
6275 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6276 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6277 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6278 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6279
6280 /* Validate. */
6281 if (!(u32Access & X86DESCATTR_UNUSABLE))
6282 {
6283 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6284 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6285 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6286 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6287 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6288 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6289 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6290 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6291 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6292 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6293 }
6294
6295 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6296 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6297 }
6298
6299 /*
6300 * Guest IDTR.
6301 */
6302 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6303 {
6304 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6305
6306 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6307 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6308
6309 /* Validate. */
6310 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6311
6312 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6313 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6314 }
6315
6316 return VINF_SUCCESS;
6317}
6318
6319
6320/**
6321 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6322 * areas.
6323 *
6324 * These MSRs will automatically be loaded to the host CPU on every successful
6325 * VM-entry and stored from the host CPU on every successful VM-exit.
6326 *
6327 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6328 * actual host MSR values are not- updated here for performance reasons. See
6329 * hmR0VmxExportHostMsrs().
6330 *
6331 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6332 *
6333 * @returns VBox status code.
6334 * @param pVCpu The cross context virtual CPU structure.
6335 * @param pVmxTransient The VMX-transient structure.
6336 *
6337 * @remarks No-long-jump zone!!!
6338 */
6339static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6340{
6341 AssertPtr(pVCpu);
6342 AssertPtr(pVmxTransient);
6343
6344 PVM pVM = pVCpu->CTX_SUFF(pVM);
6345 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6346
6347 /*
6348 * MSRs that we use the auto-load/store MSR area in the VMCS.
6349 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6350 * nothing to do here. The host MSR values are updated when it's safe in
6351 * hmR0VmxLazySaveHostMsrs().
6352 *
6353 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6354 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6355 * emulation, nothing to do here.
6356 */
6357 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6358 {
6359 /* No auto-load/store MSRs currently. */
6360 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6361 }
6362
6363 /*
6364 * Guest Sysenter MSRs.
6365 */
6366 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6367 {
6368 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6369
6370 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6371 {
6372 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6373 AssertRC(rc);
6374 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6375 }
6376
6377 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6378 {
6379 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6380 AssertRC(rc);
6381 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6382 }
6383
6384 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6385 {
6386 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6387 AssertRC(rc);
6388 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6389 }
6390 }
6391
6392 /*
6393 * Guest/host EFER MSR.
6394 */
6395 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6396 {
6397 /* Whether we are using the VMCS to swap the EFER MSR must have been
6398 determined earlier while exporting VM-entry/VM-exit controls. */
6399 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6400 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6401
6402 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6403 {
6404 /*
6405 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6406 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6407 */
6408 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6409 {
6410 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6411 AssertRC(rc);
6412 }
6413 else
6414 {
6415 /*
6416 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6417 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6418 */
6419 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6420 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6421 AssertRCReturn(rc, rc);
6422 }
6423 }
6424 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6425 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6426
6427 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6428 }
6429
6430 /*
6431 * Other MSRs.
6432 * Speculation Control (R/W).
6433 */
6434 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6435 {
6436 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6437 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6438 {
6439 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6440 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6441 AssertRCReturn(rc, rc);
6442 }
6443 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6444 }
6445
6446 return VINF_SUCCESS;
6447}
6448
6449
6450/**
6451 * Selects up the appropriate function to run guest code.
6452 *
6453 * @returns VBox status code.
6454 * @param pVCpu The cross context virtual CPU structure.
6455 * @param pVmxTransient The VMX-transient structure.
6456 *
6457 * @remarks No-long-jump zone!!!
6458 */
6459static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6460{
6461 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6462 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6463
6464 if (CPUMIsGuestInLongModeEx(pCtx))
6465 {
6466#ifndef VBOX_WITH_64_BITS_GUESTS
6467 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6468#else
6469 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6470 /* Guest is in long mode, use the 64-bit handler (host is 64-bit). */
6471 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6472#endif
6473 }
6474 else
6475 {
6476 /* Guest is not in long mode, use the 32-bit handler. */
6477 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6478 }
6479 Assert(pVmcsInfo->pfnStartVM);
6480 return VINF_SUCCESS;
6481}
6482
6483
6484/**
6485 * Wrapper for running the guest code in VT-x.
6486 *
6487 * @returns VBox status code, no informational status codes.
6488 * @param pVCpu The cross context virtual CPU structure.
6489 * @param pVmxTransient The VMX-transient structure.
6490 *
6491 * @remarks No-long-jump zone!!!
6492 */
6493DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
6494{
6495 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6496 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6497 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6498
6499 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6500
6501 /*
6502 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6503 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6504 * callee-saved and thus the need for this XMM wrapper.
6505 *
6506 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6507 */
6508 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6509 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6510 PVM pVM = pVCpu->CTX_SUFF(pVM);
6511#ifdef VBOX_WITH_KERNEL_USING_XMM
6512 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6513#else
6514 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6515#endif
6516 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6517 return rc;
6518}
6519
6520
6521/**
6522 * Reports world-switch error and dumps some useful debug info.
6523 *
6524 * @param pVCpu The cross context virtual CPU structure.
6525 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6526 * @param pVmxTransient The VMX-transient structure (only
6527 * exitReason updated).
6528 */
6529static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6530{
6531 Assert(pVCpu);
6532 Assert(pVmxTransient);
6533 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6534
6535 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6536 switch (rcVMRun)
6537 {
6538 case VERR_VMX_INVALID_VMXON_PTR:
6539 AssertFailed();
6540 break;
6541 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6542 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6543 {
6544 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6545 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6546 AssertRC(rc);
6547 hmR0VmxReadExitQualVmcs(pVmxTransient);
6548
6549 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6550 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6551 Cannot do it here as we may have been long preempted. */
6552
6553#ifdef VBOX_STRICT
6554 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6555 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6556 pVmxTransient->uExitReason));
6557 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6558 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6559 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6560 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6561 else
6562 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6563 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6564 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6565
6566 static struct
6567 {
6568 /** Name of the field to log. */
6569 const char *pszName;
6570 /** The VMCS field. */
6571 uint32_t uVmcsField;
6572 /** Whether host support of this field needs to be checked. */
6573 bool fCheckSupport;
6574 } const s_aVmcsFields[] =
6575 {
6576 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6577 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6578 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6579 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6580 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6581 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6582 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6583 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6584 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6585 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6586 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6587 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6588 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6589 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6590 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6591 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6592 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6593 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6594 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6595 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6596 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6597 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6598 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6599 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6600 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6601 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6602 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6603 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6604 /* The order of selector fields below are fixed! */
6605 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6606 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6607 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6608 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6609 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6610 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6611 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6612 /* End of ordered selector fields. */
6613 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6614 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6615 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6616 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6617 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6618 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6619 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6620 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6621 };
6622
6623 RTGDTR HostGdtr;
6624 ASMGetGDTR(&HostGdtr);
6625
6626 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6627 for (uint32_t i = 0; i < cVmcsFields; i++)
6628 {
6629 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6630
6631 bool fSupported;
6632 if (!s_aVmcsFields[i].fCheckSupport)
6633 fSupported = true;
6634 else
6635 {
6636 PVM pVM = pVCpu->CTX_SUFF(pVM);
6637 switch (uVmcsField)
6638 {
6639 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6640 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6641 case VMX_VMCS32_CTRL_PROC_EXEC2:
6642 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6643 break;
6644 default:
6645 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6646 }
6647 }
6648
6649 if (fSupported)
6650 {
6651 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6652 switch (uWidth)
6653 {
6654 case VMX_VMCSFIELD_WIDTH_16BIT:
6655 {
6656 uint16_t u16Val;
6657 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6658 AssertRC(rc);
6659 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6660
6661 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6662 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6663 {
6664 if (u16Val < HostGdtr.cbGdt)
6665 {
6666 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6667 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6668 "Host FS", "Host GS", "Host TR" };
6669 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6670 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6671 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6672 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6673 }
6674 else
6675 Log4((" Selector value exceeds GDT limit!\n"));
6676 }
6677 break;
6678 }
6679
6680 case VMX_VMCSFIELD_WIDTH_32BIT:
6681 {
6682 uint32_t u32Val;
6683 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6684 AssertRC(rc);
6685 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6686 break;
6687 }
6688
6689 case VMX_VMCSFIELD_WIDTH_64BIT:
6690 case VMX_VMCSFIELD_WIDTH_NATURAL:
6691 {
6692 uint64_t u64Val;
6693 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6694 AssertRC(rc);
6695 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6696 break;
6697 }
6698 }
6699 }
6700 }
6701
6702 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6703 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6704 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6705 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6706 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6707 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6708#endif /* VBOX_STRICT */
6709 break;
6710 }
6711
6712 default:
6713 /* Impossible */
6714 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6715 break;
6716 }
6717}
6718
6719
6720/**
6721 * Sets up the usage of TSC-offsetting and updates the VMCS.
6722 *
6723 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6724 * VMX-preemption timer.
6725 *
6726 * @returns VBox status code.
6727 * @param pVCpu The cross context virtual CPU structure.
6728 * @param pVmxTransient The VMX-transient structure.
6729 *
6730 * @remarks No-long-jump zone!!!
6731 */
6732static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6733{
6734 bool fOffsettedTsc;
6735 bool fParavirtTsc;
6736 uint64_t uTscOffset;
6737 PVM pVM = pVCpu->CTX_SUFF(pVM);
6738 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6739
6740 if (pVM->hm.s.vmx.fUsePreemptTimer)
6741 {
6742 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6743
6744 /* Make sure the returned values have sane upper and lower boundaries. */
6745 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6746 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6747 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6748 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6749
6750 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6751 * preemption timers here. We probably need to clamp the preemption timer,
6752 * after converting the timer value to the host. */
6753 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6754 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6755 AssertRC(rc);
6756 }
6757 else
6758 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6759
6760 if (fParavirtTsc)
6761 {
6762 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6763 information before every VM-entry, hence disable it for performance sake. */
6764#if 0
6765 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6766 AssertRC(rc);
6767#endif
6768 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6769 }
6770
6771 if ( fOffsettedTsc
6772 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6773 {
6774 if (pVmxTransient->fIsNestedGuest)
6775 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6776 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6777 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6778 }
6779 else
6780 {
6781 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6782 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6783 }
6784}
6785
6786
6787/**
6788 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6789 * VM-exit interruption info type.
6790 *
6791 * @returns The IEM exception flags.
6792 * @param uVector The event vector.
6793 * @param uVmxEventType The VMX event type.
6794 *
6795 * @remarks This function currently only constructs flags required for
6796 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6797 * and CR2 aspects of an exception are not included).
6798 */
6799static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6800{
6801 uint32_t fIemXcptFlags;
6802 switch (uVmxEventType)
6803 {
6804 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6805 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6806 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6807 break;
6808
6809 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6810 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6811 break;
6812
6813 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6814 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6815 break;
6816
6817 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6818 {
6819 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6820 if (uVector == X86_XCPT_BP)
6821 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6822 else if (uVector == X86_XCPT_OF)
6823 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6824 else
6825 {
6826 fIemXcptFlags = 0;
6827 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6828 }
6829 break;
6830 }
6831
6832 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6833 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6834 break;
6835
6836 default:
6837 fIemXcptFlags = 0;
6838 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6839 break;
6840 }
6841 return fIemXcptFlags;
6842}
6843
6844
6845/**
6846 * Sets an event as a pending event to be injected into the guest.
6847 *
6848 * @param pVCpu The cross context virtual CPU structure.
6849 * @param u32IntInfo The VM-entry interruption-information field.
6850 * @param cbInstr The VM-entry instruction length in bytes (for software
6851 * interrupts, exceptions and privileged software
6852 * exceptions).
6853 * @param u32ErrCode The VM-entry exception error code.
6854 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6855 * page-fault.
6856 */
6857DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6858 RTGCUINTPTR GCPtrFaultAddress)
6859{
6860 Assert(!pVCpu->hm.s.Event.fPending);
6861 pVCpu->hm.s.Event.fPending = true;
6862 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6863 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6864 pVCpu->hm.s.Event.cbInstr = cbInstr;
6865 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6866}
6867
6868
6869/**
6870 * Sets an external interrupt as pending-for-injection into the VM.
6871 *
6872 * @param pVCpu The cross context virtual CPU structure.
6873 * @param u8Interrupt The external interrupt vector.
6874 */
6875DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
6876{
6877 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6878 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6879 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6880 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6881 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6882}
6883
6884
6885/**
6886 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6887 *
6888 * @param pVCpu The cross context virtual CPU structure.
6889 */
6890DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
6891{
6892 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6893 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6894 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6895 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6896 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6897}
6898
6899
6900/**
6901 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6902 *
6903 * @param pVCpu The cross context virtual CPU structure.
6904 */
6905DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
6906{
6907 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6908 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6909 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6910 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6911 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6912}
6913
6914
6915/**
6916 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6917 *
6918 * @param pVCpu The cross context virtual CPU structure.
6919 */
6920DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
6921{
6922 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6923 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6924 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6925 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6926 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6927}
6928
6929
6930/**
6931 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6932 *
6933 * @param pVCpu The cross context virtual CPU structure.
6934 */
6935DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
6936{
6937 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6938 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6939 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6940 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6941 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6942}
6943
6944
6945#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
6946/**
6947 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
6948 *
6949 * @param pVCpu The cross context virtual CPU structure.
6950 * @param u32ErrCode The error code for the general-protection exception.
6951 */
6952DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
6953{
6954 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
6955 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6956 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6957 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6958 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6959}
6960
6961
6962/**
6963 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
6964 *
6965 * @param pVCpu The cross context virtual CPU structure.
6966 * @param u32ErrCode The error code for the stack exception.
6967 */
6968DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
6969{
6970 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
6971 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6972 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6973 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6974 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
6975}
6976#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
6977
6978
6979/**
6980 * Fixes up attributes for the specified segment register.
6981 *
6982 * @param pVCpu The cross context virtual CPU structure.
6983 * @param pSelReg The segment register that needs fixing.
6984 * @param idxSel The VMCS field for the corresponding segment register.
6985 */
6986static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
6987{
6988 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
6989
6990 /*
6991 * If VT-x marks the segment as unusable, most other bits remain undefined:
6992 * - For CS the L, D and G bits have meaning.
6993 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
6994 * - For the remaining data segments no bits are defined.
6995 *
6996 * The present bit and the unusable bit has been observed to be set at the
6997 * same time (the selector was supposed to be invalid as we started executing
6998 * a V8086 interrupt in ring-0).
6999 *
7000 * What should be important for the rest of the VBox code, is that the P bit is
7001 * cleared. Some of the other VBox code recognizes the unusable bit, but
7002 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7003 * safe side here, we'll strip off P and other bits we don't care about. If
7004 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7005 *
7006 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7007 */
7008#ifdef VBOX_STRICT
7009 uint32_t const uAttr = pSelReg->Attr.u;
7010#endif
7011
7012 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7013 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7014 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7015
7016#ifdef VBOX_STRICT
7017 VMMRZCallRing3Disable(pVCpu);
7018 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7019# ifdef DEBUG_bird
7020 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7021 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7022 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7023# endif
7024 VMMRZCallRing3Enable(pVCpu);
7025 NOREF(uAttr);
7026#endif
7027 RT_NOREF2(pVCpu, idxSel);
7028}
7029
7030
7031/**
7032 * Imports a guest segment register from the current VMCS into the guest-CPU
7033 * context.
7034 *
7035 * @param pVCpu The cross context virtual CPU structure.
7036 * @param iSegReg The segment register number (X86_SREG_XXX).
7037 *
7038 * @remarks Called with interrupts and/or preemption disabled.
7039 */
7040static void hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7041{
7042 Assert(iSegReg < X86_SREG_COUNT);
7043
7044 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7045 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7046 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7047 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7048
7049 uint16_t u16Sel;
7050 uint64_t u64Base;
7051 uint32_t u32Limit, u32Attr;
7052 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7053 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7054 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7055 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7056
7057 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7058 pSelReg->Sel = u16Sel;
7059 pSelReg->ValidSel = u16Sel;
7060 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7061 pSelReg->u32Limit = u32Limit;
7062 pSelReg->u64Base = u64Base;
7063 pSelReg->Attr.u = u32Attr;
7064 if (u32Attr & X86DESCATTR_UNUSABLE)
7065 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7066}
7067
7068
7069/**
7070 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7071 *
7072 * @param pVCpu The cross context virtual CPU structure.
7073 *
7074 * @remarks Called with interrupts and/or preemption disabled.
7075 */
7076static void hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7077{
7078 uint16_t u16Sel;
7079 uint64_t u64Base;
7080 uint32_t u32Limit, u32Attr;
7081 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7082 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7083 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7084 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7085
7086 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7087 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7088 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7089 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7090 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7091 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7092 if (u32Attr & X86DESCATTR_UNUSABLE)
7093 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7094}
7095
7096
7097/**
7098 * Imports the guest TR from the current VMCS into the guest-CPU context.
7099 *
7100 * @param pVCpu The cross context virtual CPU structure.
7101 *
7102 * @remarks Called with interrupts and/or preemption disabled.
7103 */
7104static void hmR0VmxImportGuestTr(PVMCPU pVCpu)
7105{
7106 uint16_t u16Sel;
7107 uint64_t u64Base;
7108 uint32_t u32Limit, u32Attr;
7109 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7110 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7111 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7112 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7113
7114 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7115 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7116 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7117 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7118 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7119 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7120 /* TR is the only selector that can never be unusable. */
7121 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7122}
7123
7124
7125/**
7126 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7127 *
7128 * @param pVCpu The cross context virtual CPU structure.
7129 *
7130 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7131 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7132 * instead!!!
7133 */
7134static void hmR0VmxImportGuestRip(PVMCPU pVCpu)
7135{
7136 uint64_t u64Val;
7137 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7138 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7139 {
7140 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7141 AssertRC(rc);
7142
7143 pCtx->rip = u64Val;
7144 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7145 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7146 }
7147}
7148
7149
7150/**
7151 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7152 *
7153 * @param pVCpu The cross context virtual CPU structure.
7154 * @param pVmcsInfo The VMCS info. object.
7155 *
7156 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7157 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7158 * instead!!!
7159 */
7160static void hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7161{
7162 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7163 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7164 {
7165 uint64_t u64Val;
7166 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7167 AssertRC(rc);
7168
7169 pCtx->rflags.u64 = u64Val;
7170 if (pVmcsInfo->RealMode.fRealOnV86Active)
7171 {
7172 pCtx->eflags.Bits.u1VM = 0;
7173 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7174 }
7175 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7176 }
7177}
7178
7179
7180/**
7181 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7182 * context.
7183 *
7184 * @param pVCpu The cross context virtual CPU structure.
7185 * @param pVmcsInfo The VMCS info. object.
7186 *
7187 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7188 * do not log!
7189 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7190 * instead!!!
7191 */
7192static void hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7193{
7194 uint32_t u32Val;
7195 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7196 if (!u32Val)
7197 {
7198 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7199 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7200 CPUMSetGuestNmiBlocking(pVCpu, false);
7201 }
7202 else
7203 {
7204 /*
7205 * We must import RIP here to set our EM interrupt-inhibited state.
7206 * We also import RFLAGS as our code that evaluates pending interrupts
7207 * before VM-entry requires it.
7208 */
7209 hmR0VmxImportGuestRip(pVCpu);
7210 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7211
7212 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7213 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7214 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7215 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7216
7217 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7218 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7219 }
7220}
7221
7222
7223/**
7224 * Worker for VMXR0ImportStateOnDemand.
7225 *
7226 * @returns VBox status code.
7227 * @param pVCpu The cross context virtual CPU structure.
7228 * @param pVmcsInfo The VMCS info. object.
7229 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7230 */
7231static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7232{
7233 int rc = VINF_SUCCESS;
7234 PVM pVM = pVCpu->CTX_SUFF(pVM);
7235 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7236 uint32_t u32Val;
7237
7238 /*
7239 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7240 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7241 * neither are other host platforms.
7242 *
7243 * Committing this temporarily as it prevents BSOD.
7244 *
7245 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7246 */
7247#ifdef RT_OS_WINDOWS
7248 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7249 return VERR_HM_IPE_1;
7250#endif
7251
7252 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7253
7254 /*
7255 * We disable interrupts to make the updating of the state and in particular
7256 * the fExtrn modification atomic wrt to preemption hooks.
7257 */
7258 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7259
7260 fWhat &= pCtx->fExtrn;
7261 if (fWhat)
7262 {
7263 do
7264 {
7265 if (fWhat & CPUMCTX_EXTRN_RIP)
7266 hmR0VmxImportGuestRip(pVCpu);
7267
7268 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7269 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7270
7271 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7272 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7273
7274 if (fWhat & CPUMCTX_EXTRN_RSP)
7275 {
7276 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7277 AssertRC(rc);
7278 }
7279
7280 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7281 {
7282 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7283 if (fWhat & CPUMCTX_EXTRN_CS)
7284 {
7285 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7286 hmR0VmxImportGuestRip(pVCpu);
7287 if (fRealOnV86Active)
7288 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7289 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7290 }
7291 if (fWhat & CPUMCTX_EXTRN_SS)
7292 {
7293 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7294 if (fRealOnV86Active)
7295 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7296 }
7297 if (fWhat & CPUMCTX_EXTRN_DS)
7298 {
7299 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7300 if (fRealOnV86Active)
7301 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7302 }
7303 if (fWhat & CPUMCTX_EXTRN_ES)
7304 {
7305 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7306 if (fRealOnV86Active)
7307 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7308 }
7309 if (fWhat & CPUMCTX_EXTRN_FS)
7310 {
7311 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7312 if (fRealOnV86Active)
7313 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7314 }
7315 if (fWhat & CPUMCTX_EXTRN_GS)
7316 {
7317 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7318 if (fRealOnV86Active)
7319 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7320 }
7321 }
7322
7323 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7324 {
7325 if (fWhat & CPUMCTX_EXTRN_LDTR)
7326 hmR0VmxImportGuestLdtr(pVCpu);
7327
7328 if (fWhat & CPUMCTX_EXTRN_GDTR)
7329 {
7330 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7331 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7332 pCtx->gdtr.cbGdt = u32Val;
7333 }
7334
7335 /* Guest IDTR. */
7336 if (fWhat & CPUMCTX_EXTRN_IDTR)
7337 {
7338 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7339 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7340 pCtx->idtr.cbIdt = u32Val;
7341 }
7342
7343 /* Guest TR. */
7344 if (fWhat & CPUMCTX_EXTRN_TR)
7345 {
7346 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7347 don't need to import that one. */
7348 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7349 hmR0VmxImportGuestTr(pVCpu);
7350 }
7351 }
7352
7353 if (fWhat & CPUMCTX_EXTRN_DR7)
7354 {
7355 if (!pVCpu->hm.s.fUsingHyperDR7)
7356 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7357 }
7358
7359 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7360 {
7361 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7362 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7363 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7364 pCtx->SysEnter.cs = u32Val;
7365 }
7366
7367 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7368 {
7369 if ( pVM->hm.s.fAllow64BitGuests
7370 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7371 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7372 }
7373
7374 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7375 {
7376 if ( pVM->hm.s.fAllow64BitGuests
7377 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7378 {
7379 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7380 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7381 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7382 }
7383 }
7384
7385 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7386 {
7387 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7388 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7389 Assert(pMsrs);
7390 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7391 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7392 for (uint32_t i = 0; i < cMsrs; i++)
7393 {
7394 uint32_t const idMsr = pMsrs[i].u32Msr;
7395 switch (idMsr)
7396 {
7397 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7398 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7399 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7400 default:
7401 {
7402 pCtx->fExtrn = 0;
7403 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7404 ASMSetFlags(fEFlags);
7405 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7406 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7407 }
7408 }
7409 }
7410 }
7411
7412 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7413 {
7414 if (fWhat & CPUMCTX_EXTRN_CR0)
7415 {
7416 uint64_t u64Cr0;
7417 uint64_t u64Shadow;
7418 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7419 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7420 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7421 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7422#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7423 /*
7424 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
7425 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
7426 */
7427 if (CPUMIsGuestInVmxNonRootMode(pCtx))
7428 {
7429 u64Cr0 |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
7430 u64Cr0 &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
7431 }
7432#endif
7433 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7434 CPUMSetGuestCR0(pVCpu, u64Cr0);
7435 VMMRZCallRing3Enable(pVCpu);
7436 }
7437
7438 if (fWhat & CPUMCTX_EXTRN_CR4)
7439 {
7440 uint64_t u64Cr4;
7441 uint64_t u64Shadow;
7442 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7443 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7444 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7445 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7446#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7447 /*
7448 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
7449 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
7450 */
7451 if (CPUMIsGuestInVmxNonRootMode(pCtx))
7452 {
7453 u64Cr4 |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
7454 u64Cr4 &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
7455 }
7456#endif
7457 pCtx->cr4 = u64Cr4;
7458 }
7459
7460 if (fWhat & CPUMCTX_EXTRN_CR3)
7461 {
7462 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7463 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7464 || ( pVM->hm.s.fNestedPaging
7465 && CPUMIsGuestPagingEnabledEx(pCtx)))
7466 {
7467 uint64_t u64Cr3;
7468 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7469 if (pCtx->cr3 != u64Cr3)
7470 {
7471 pCtx->cr3 = u64Cr3;
7472 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7473 }
7474
7475 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7476 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7477 if (CPUMIsGuestInPAEModeEx(pCtx))
7478 {
7479 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7480 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7481 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7482 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7483 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7484 }
7485 }
7486 }
7487 }
7488
7489#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7490 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7491 {
7492 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7493 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7494 {
7495 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7496 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7497 if (RT_SUCCESS(rc))
7498 { /* likely */ }
7499 else
7500 break;
7501 }
7502 }
7503#endif
7504 } while (0);
7505
7506 if (RT_SUCCESS(rc))
7507 {
7508 /* Update fExtrn. */
7509 pCtx->fExtrn &= ~fWhat;
7510
7511 /* If everything has been imported, clear the HM keeper bit. */
7512 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7513 {
7514 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7515 Assert(!pCtx->fExtrn);
7516 }
7517 }
7518 }
7519 else
7520 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7521
7522 /*
7523 * Restore interrupts.
7524 */
7525 ASMSetFlags(fEFlags);
7526
7527 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7528
7529 if (RT_SUCCESS(rc))
7530 { /* likely */ }
7531 else
7532 return rc;
7533
7534 /*
7535 * Honor any pending CR3 updates.
7536 *
7537 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
7538 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7539 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7540 *
7541 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7542 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7543 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7544 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7545 *
7546 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7547 */
7548 if (VMMRZCallRing3IsEnabled(pVCpu))
7549 {
7550 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7551 {
7552 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7553 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7554 }
7555
7556 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7557 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7558
7559 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7560 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7561 }
7562
7563 return VINF_SUCCESS;
7564}
7565
7566
7567/**
7568 * Saves the guest state from the VMCS into the guest-CPU context.
7569 *
7570 * @returns VBox status code.
7571 * @param pVCpu The cross context virtual CPU structure.
7572 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7573 */
7574VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
7575{
7576 AssertPtr(pVCpu);
7577 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7578 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7579}
7580
7581
7582/**
7583 * Check per-VM and per-VCPU force flag actions that require us to go back to
7584 * ring-3 for one reason or another.
7585 *
7586 * @returns Strict VBox status code (i.e. informational status codes too)
7587 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7588 * ring-3.
7589 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7590 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7591 * interrupts)
7592 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7593 * all EMTs to be in ring-3.
7594 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7595 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7596 * to the EM loop.
7597 *
7598 * @param pVCpu The cross context virtual CPU structure.
7599 * @param fStepping Whether we are single-stepping the guest using the
7600 * hypervisor debugger.
7601 *
7602 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7603 * is no longer in VMX non-root mode.
7604 */
7605static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
7606{
7607 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7608
7609 /*
7610 * Update pending interrupts into the APIC's IRR.
7611 */
7612 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7613 APICUpdatePendingInterrupts(pVCpu);
7614
7615 /*
7616 * Anything pending? Should be more likely than not if we're doing a good job.
7617 */
7618 PVM pVM = pVCpu->CTX_SUFF(pVM);
7619 if ( !fStepping
7620 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7621 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7622 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7623 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7624 return VINF_SUCCESS;
7625
7626 /* Pending PGM C3 sync. */
7627 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7628 {
7629 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7630 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7631 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7632 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7633 if (rcStrict != VINF_SUCCESS)
7634 {
7635 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7636 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7637 return rcStrict;
7638 }
7639 }
7640
7641 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7642 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7643 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7644 {
7645 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7646 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7647 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7648 return rc;
7649 }
7650
7651 /* Pending VM request packets, such as hardware interrupts. */
7652 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7653 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7654 {
7655 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7656 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7657 return VINF_EM_PENDING_REQUEST;
7658 }
7659
7660 /* Pending PGM pool flushes. */
7661 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7662 {
7663 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7664 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7665 return VINF_PGM_POOL_FLUSH_PENDING;
7666 }
7667
7668 /* Pending DMA requests. */
7669 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7670 {
7671 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7672 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7673 return VINF_EM_RAW_TO_R3;
7674 }
7675
7676#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7677 /* Pending nested-guest APIC-write (has highest priority among nested-guest FFs). */
7678 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7679 {
7680 Log4Func(("Pending nested-guest APIC-write\n"));
7681 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7682 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7683 return rcStrict;
7684 }
7685 /** @todo VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_PREEMPT_TIMER */
7686#endif
7687
7688 return VINF_SUCCESS;
7689}
7690
7691
7692/**
7693 * Converts any TRPM trap into a pending HM event. This is typically used when
7694 * entering from ring-3 (not longjmp returns).
7695 *
7696 * @param pVCpu The cross context virtual CPU structure.
7697 */
7698static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
7699{
7700 Assert(TRPMHasTrap(pVCpu));
7701 Assert(!pVCpu->hm.s.Event.fPending);
7702
7703 uint8_t uVector;
7704 TRPMEVENT enmTrpmEvent;
7705 RTGCUINT uErrCode;
7706 RTGCUINTPTR GCPtrFaultAddress;
7707 uint8_t cbInstr;
7708
7709 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
7710 AssertRC(rc);
7711
7712 uint32_t u32IntInfo;
7713 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7714 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
7715
7716 rc = TRPMResetTrap(pVCpu);
7717 AssertRC(rc);
7718 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7719 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7720
7721 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7722}
7723
7724
7725/**
7726 * Converts the pending HM event into a TRPM trap.
7727 *
7728 * @param pVCpu The cross context virtual CPU structure.
7729 */
7730static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
7731{
7732 Assert(pVCpu->hm.s.Event.fPending);
7733
7734 /* If a trap was already pending, we did something wrong! */
7735 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7736
7737 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7738 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7739 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7740
7741 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7742
7743 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7744 AssertRC(rc);
7745
7746 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7747 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7748
7749 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7750 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7751 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7752 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7753
7754 /* We're now done converting the pending event. */
7755 pVCpu->hm.s.Event.fPending = false;
7756}
7757
7758
7759/**
7760 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7761 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7762 *
7763 * @param pVCpu The cross context virtual CPU structure.
7764 * @param pVmcsInfo The VMCS info. object.
7765 */
7766static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
7767{
7768 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7769 {
7770 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7771 {
7772 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7773 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7774 AssertRC(rc);
7775 }
7776 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7777}
7778
7779
7780/**
7781 * Clears the interrupt-window exiting control in the VMCS.
7782 *
7783 * @param pVmcsInfo The VMCS info. object.
7784 */
7785DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7786{
7787 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7788 {
7789 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7790 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7791 AssertRC(rc);
7792 }
7793}
7794
7795
7796/**
7797 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7798 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7799 *
7800 * @param pVCpu The cross context virtual CPU structure.
7801 * @param pVmcsInfo The VMCS info. object.
7802 */
7803static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
7804{
7805 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7806 {
7807 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7808 {
7809 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7810 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7811 AssertRC(rc);
7812 Log4Func(("Setup NMI-window exiting\n"));
7813 }
7814 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7815}
7816
7817
7818/**
7819 * Clears the NMI-window exiting control in the VMCS.
7820 *
7821 * @param pVmcsInfo The VMCS info. object.
7822 */
7823DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7824{
7825 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7826 {
7827 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7828 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7829 AssertRC(rc);
7830 }
7831}
7832
7833
7834/**
7835 * Does the necessary state syncing before returning to ring-3 for any reason
7836 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7837 *
7838 * @returns VBox status code.
7839 * @param pVCpu The cross context virtual CPU structure.
7840 * @param fImportState Whether to import the guest state from the VMCS back
7841 * to the guest-CPU context.
7842 *
7843 * @remarks No-long-jmp zone!!!
7844 */
7845static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
7846{
7847 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7848 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7849
7850 RTCPUID const idCpu = RTMpCpuId();
7851 Log4Func(("HostCpuId=%u\n", idCpu));
7852
7853 /*
7854 * !!! IMPORTANT !!!
7855 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
7856 */
7857
7858 /* Save the guest state if necessary. */
7859 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7860 if (fImportState)
7861 {
7862 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7863 AssertRCReturn(rc, rc);
7864 }
7865
7866 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7867 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7868 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7869
7870 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7871#ifdef VBOX_STRICT
7872 if (CPUMIsHyperDebugStateActive(pVCpu))
7873 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7874#endif
7875 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7876 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7877 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7878
7879 /* Restore host-state bits that VT-x only restores partially. */
7880 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7881 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7882 {
7883 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7884 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7885 }
7886 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7887
7888 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7889 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7890 {
7891 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7892 if (!fImportState)
7893 {
7894 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7895 AssertRCReturn(rc, rc);
7896 }
7897 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7898 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7899 }
7900 else
7901 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7902
7903 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7904 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7905
7906 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7907 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7908 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7909 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7910 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7911 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7912 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
7913 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
7914 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
7915 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
7916
7917 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
7918
7919 /** @todo This partially defeats the purpose of having preemption hooks.
7920 * The problem is, deregistering the hooks should be moved to a place that
7921 * lasts until the EMT is about to be destroyed not everytime while leaving HM
7922 * context.
7923 */
7924 int rc = hmR0VmxClearVmcs(pVmcsInfo);
7925 AssertRCReturn(rc, rc);
7926
7927#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7928 /*
7929 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
7930 * clear a shadow VMCS before allowing that VMCS to become active on another
7931 * logical processor. We may or may not be importing guest state which clears
7932 * it, so cover for it here.
7933 *
7934 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
7935 */
7936 if ( pVmcsInfo->pvShadowVmcs
7937 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
7938 {
7939 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
7940 AssertRCReturn(rc, rc);
7941 }
7942
7943 /*
7944 * Flag that we need to re-import the host state if we switch to this VMCS before
7945 * executing guest or nested-guest code.
7946 */
7947 pVmcsInfo->idHostCpu = NIL_RTCPUID;
7948#endif
7949
7950 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
7951 NOREF(idCpu);
7952 return VINF_SUCCESS;
7953}
7954
7955
7956/**
7957 * Leaves the VT-x session.
7958 *
7959 * @returns VBox status code.
7960 * @param pVCpu The cross context virtual CPU structure.
7961 *
7962 * @remarks No-long-jmp zone!!!
7963 */
7964static int hmR0VmxLeaveSession(PVMCPU pVCpu)
7965{
7966 HM_DISABLE_PREEMPT(pVCpu);
7967 HMVMX_ASSERT_CPU_SAFE(pVCpu);
7968 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7969 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7970
7971 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
7972 and done this from the VMXR0ThreadCtxCallback(). */
7973 if (!pVCpu->hm.s.fLeaveDone)
7974 {
7975 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
7976 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
7977 pVCpu->hm.s.fLeaveDone = true;
7978 }
7979 Assert(!pVCpu->cpum.GstCtx.fExtrn);
7980
7981 /*
7982 * !!! IMPORTANT !!!
7983 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
7984 */
7985
7986 /* Deregister hook now that we've left HM context before re-enabling preemption. */
7987 /** @todo Deregistering here means we need to VMCLEAR always
7988 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
7989 * for calling VMMR0ThreadCtxHookDisable here! */
7990 VMMR0ThreadCtxHookDisable(pVCpu);
7991
7992 /* Leave HM context. This takes care of local init (term). */
7993 int rc = HMR0LeaveCpu(pVCpu);
7994
7995 HM_RESTORE_PREEMPT();
7996 return rc;
7997}
7998
7999
8000/**
8001 * Does the necessary state syncing before doing a longjmp to ring-3.
8002 *
8003 * @returns VBox status code.
8004 * @param pVCpu The cross context virtual CPU structure.
8005 *
8006 * @remarks No-long-jmp zone!!!
8007 */
8008DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8009{
8010 return hmR0VmxLeaveSession(pVCpu);
8011}
8012
8013
8014/**
8015 * Take necessary actions before going back to ring-3.
8016 *
8017 * An action requires us to go back to ring-3. This function does the necessary
8018 * steps before we can safely return to ring-3. This is not the same as longjmps
8019 * to ring-3, this is voluntary and prepares the guest so it may continue
8020 * executing outside HM (recompiler/IEM).
8021 *
8022 * @returns VBox status code.
8023 * @param pVCpu The cross context virtual CPU structure.
8024 * @param rcExit The reason for exiting to ring-3. Can be
8025 * VINF_VMM_UNKNOWN_RING3_CALL.
8026 */
8027static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8028{
8029 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8030
8031 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8032 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8033 {
8034 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8035 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8036 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8037 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8038 }
8039
8040 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8041 VMMRZCallRing3Disable(pVCpu);
8042 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8043
8044 /*
8045 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8046 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8047 *
8048 * This is because execution may continue from ring-3 and we would need to inject
8049 * the event from there (hence place it back in TRPM).
8050 */
8051 if (pVCpu->hm.s.Event.fPending)
8052 {
8053 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8054 Assert(!pVCpu->hm.s.Event.fPending);
8055
8056 /* Clear the events from the VMCS. */
8057 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8058 AssertRC(rc);
8059 }
8060#ifdef VBOX_STRICT
8061 else
8062 {
8063 /*
8064 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8065 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8066 * occasionally, see @bugref{9180#c42}.
8067 *
8068 * However, if the VM-entry failed, any VM entry-interruption info. field would
8069 * be left unmodified as the event would not have been injected to the guest. In
8070 * such cases, don't assert, we're not going to continue guest execution anyway.
8071 */
8072 uint32_t uExitReason;
8073 uint32_t uEntryIntInfo;
8074 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8075 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8076 AssertRC(rc);
8077 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8078 }
8079#endif
8080
8081 /*
8082 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8083 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8084 * (e.g. TPR below threshold).
8085 */
8086 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8087 {
8088 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8089 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8090 }
8091
8092 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8093 and if we're injecting an event we should have a TRPM trap pending. */
8094 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8095#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8096 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8097#endif
8098
8099 /* Save guest state and restore host state bits. */
8100 int rc = hmR0VmxLeaveSession(pVCpu);
8101 AssertRCReturn(rc, rc);
8102 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8103
8104 /* Thread-context hooks are unregistered at this point!!! */
8105
8106 /* Sync recompiler state. */
8107 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8108 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8109 | CPUM_CHANGED_LDTR
8110 | CPUM_CHANGED_GDTR
8111 | CPUM_CHANGED_IDTR
8112 | CPUM_CHANGED_TR
8113 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8114 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8115 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8116 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8117
8118 Assert(!pVCpu->hm.s.fClearTrapFlag);
8119
8120 /* Update the exit-to-ring 3 reason. */
8121 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8122
8123 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8124 if ( rcExit != VINF_EM_RAW_INTERRUPT
8125 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8126 {
8127 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8128 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8129 }
8130
8131 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8132
8133 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
8134 VMMRZCallRing3RemoveNotification(pVCpu);
8135 VMMRZCallRing3Enable(pVCpu);
8136
8137 return rc;
8138}
8139
8140
8141/**
8142 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8143 * longjump to ring-3 and possibly get preempted.
8144 *
8145 * @returns VBox status code.
8146 * @param pVCpu The cross context virtual CPU structure.
8147 * @param enmOperation The operation causing the ring-3 longjump.
8148 * @param pvUser User argument, currently unused, NULL.
8149 */
8150static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
8151{
8152 RT_NOREF(pvUser);
8153 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8154 {
8155 /*
8156 * !!! IMPORTANT !!!
8157 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8158 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8159 */
8160 VMMRZCallRing3RemoveNotification(pVCpu);
8161 VMMRZCallRing3Disable(pVCpu);
8162 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
8163 RTThreadPreemptDisable(&PreemptState);
8164
8165 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8166 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8167 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8168 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8169
8170 /* Restore host-state bits that VT-x only restores partially. */
8171 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8172 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8173 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8174 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8175
8176 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8177 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8178 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8179
8180 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8181 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8182 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8183
8184 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8185 cleared as part of importing the guest state above. */
8186 hmR0VmxClearVmcs(pVmcsInfo);
8187
8188 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8189 VMMR0ThreadCtxHookDisable(pVCpu);
8190 HMR0LeaveCpu(pVCpu);
8191 RTThreadPreemptRestore(&PreemptState);
8192 return VINF_SUCCESS;
8193 }
8194
8195 Assert(pVCpu);
8196 Assert(pvUser);
8197 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8198 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8199
8200 VMMRZCallRing3Disable(pVCpu);
8201 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8202
8203 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8204
8205 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8206 AssertRCReturn(rc, rc);
8207
8208 VMMRZCallRing3Enable(pVCpu);
8209 return VINF_SUCCESS;
8210}
8211
8212
8213/**
8214 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8215 * stack.
8216 *
8217 * @returns Strict VBox status code (i.e. informational status codes too).
8218 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8219 * @param pVCpu The cross context virtual CPU structure.
8220 * @param uValue The value to push to the guest stack.
8221 */
8222static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
8223{
8224 /*
8225 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8226 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8227 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8228 */
8229 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8230 if (pCtx->sp == 1)
8231 return VINF_EM_RESET;
8232 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8233 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8234 AssertRC(rc);
8235 return rc;
8236}
8237
8238
8239/**
8240 * Injects an event into the guest upon VM-entry by updating the relevant fields
8241 * in the VM-entry area in the VMCS.
8242 *
8243 * @returns Strict VBox status code (i.e. informational status codes too).
8244 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8245 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8246 *
8247 * @param pVCpu The cross context virtual CPU structure.
8248 * @param pVmxTransient The VMX-transient structure.
8249 * @param pEvent The event being injected.
8250 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8251 * will be updated if necessary. This cannot not be NULL.
8252 * @param fStepping Whether we're single-stepping guest execution and should
8253 * return VINF_EM_DBG_STEPPED if the event is injected
8254 * directly (registers modified by us, not by hardware on
8255 * VM-entry).
8256 */
8257static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8258 uint32_t *pfIntrState)
8259{
8260 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8261 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8262 Assert(pfIntrState);
8263
8264 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8265 uint32_t u32IntInfo = pEvent->u64IntInfo;
8266 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8267 uint32_t const cbInstr = pEvent->cbInstr;
8268 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8269 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8270 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8271
8272#ifdef VBOX_STRICT
8273 /*
8274 * Validate the error-code-valid bit for hardware exceptions.
8275 * No error codes for exceptions in real-mode.
8276 *
8277 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8278 */
8279 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8280 && !CPUMIsGuestInRealModeEx(pCtx))
8281 {
8282 switch (uVector)
8283 {
8284 case X86_XCPT_PF:
8285 case X86_XCPT_DF:
8286 case X86_XCPT_TS:
8287 case X86_XCPT_NP:
8288 case X86_XCPT_SS:
8289 case X86_XCPT_GP:
8290 case X86_XCPT_AC:
8291 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8292 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8293 RT_FALL_THRU();
8294 default:
8295 break;
8296 }
8297 }
8298
8299 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8300 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8301 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8302#endif
8303
8304 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8305
8306 /*
8307 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8308 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8309 * interrupt handler in the (real-mode) guest.
8310 *
8311 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8312 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8313 */
8314 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8315 {
8316 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8317 {
8318 /*
8319 * For CPUs with unrestricted guest execution enabled and with the guest
8320 * in real-mode, we must not set the deliver-error-code bit.
8321 *
8322 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8323 */
8324 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8325 }
8326 else
8327 {
8328 PVM pVM = pVCpu->CTX_SUFF(pVM);
8329 Assert(PDMVmmDevHeapIsEnabled(pVM));
8330 Assert(pVM->hm.s.vmx.pRealModeTSS);
8331 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8332
8333 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8334 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8335 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8336 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8337 AssertRCReturn(rc2, rc2);
8338
8339 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8340 size_t const cbIdtEntry = sizeof(X86IDTR16);
8341 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8342 {
8343 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8344 if (uVector == X86_XCPT_DF)
8345 return VINF_EM_RESET;
8346
8347 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8348 No error codes for exceptions in real-mode. */
8349 if (uVector == X86_XCPT_GP)
8350 {
8351 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8352 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8353 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8354 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8355 HMEVENT EventXcptDf;
8356 RT_ZERO(EventXcptDf);
8357 EventXcptDf.u64IntInfo = uXcptDfInfo;
8358 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8359 }
8360
8361 /*
8362 * If we're injecting an event with no valid IDT entry, inject a #GP.
8363 * No error codes for exceptions in real-mode.
8364 *
8365 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8366 */
8367 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8368 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8369 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8370 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8371 HMEVENT EventXcptGp;
8372 RT_ZERO(EventXcptGp);
8373 EventXcptGp.u64IntInfo = uXcptGpInfo;
8374 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8375 }
8376
8377 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8378 uint16_t uGuestIp = pCtx->ip;
8379 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8380 {
8381 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8382 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8383 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8384 }
8385 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8386 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8387
8388 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8389 X86IDTR16 IdtEntry;
8390 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8391 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8392 AssertRCReturn(rc2, rc2);
8393
8394 /* Construct the stack frame for the interrupt/exception handler. */
8395 VBOXSTRICTRC rcStrict;
8396 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8397 if (rcStrict == VINF_SUCCESS)
8398 {
8399 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8400 if (rcStrict == VINF_SUCCESS)
8401 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8402 }
8403
8404 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8405 if (rcStrict == VINF_SUCCESS)
8406 {
8407 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8408 pCtx->rip = IdtEntry.offSel;
8409 pCtx->cs.Sel = IdtEntry.uSel;
8410 pCtx->cs.ValidSel = IdtEntry.uSel;
8411 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8412 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8413 && uVector == X86_XCPT_PF)
8414 pCtx->cr2 = GCPtrFault;
8415
8416 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8417 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8418 | HM_CHANGED_GUEST_RSP);
8419
8420 /*
8421 * If we delivered a hardware exception (other than an NMI) and if there was
8422 * block-by-STI in effect, we should clear it.
8423 */
8424 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8425 {
8426 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8427 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8428 Log4Func(("Clearing inhibition due to STI\n"));
8429 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8430 }
8431
8432 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8433 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8434
8435 /*
8436 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8437 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8438 */
8439 pVCpu->hm.s.Event.fPending = false;
8440
8441 /*
8442 * If we eventually support nested-guest execution without unrestricted guest execution,
8443 * we should set fInterceptEvents here.
8444 */
8445 Assert(!pVmxTransient->fIsNestedGuest);
8446
8447 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8448 if (fStepping)
8449 rcStrict = VINF_EM_DBG_STEPPED;
8450 }
8451 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8452 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8453 return rcStrict;
8454 }
8455 }
8456
8457 /*
8458 * Validate.
8459 */
8460 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8461 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8462
8463 /*
8464 * Inject the event into the VMCS.
8465 */
8466 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8467 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8468 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8469 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8470 AssertRC(rc);
8471
8472 /*
8473 * Update guest CR2 if this is a page-fault.
8474 */
8475 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8476 pCtx->cr2 = GCPtrFault;
8477
8478 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8479 return VINF_SUCCESS;
8480}
8481
8482
8483/**
8484 * Evaluates the event to be delivered to the guest and sets it as the pending
8485 * event.
8486 *
8487 * @returns Strict VBox status code (i.e. informational status codes too).
8488 * @param pVCpu The cross context virtual CPU structure.
8489 * @param pVmxTransient The VMX-transient structure.
8490 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8491 */
8492static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8493{
8494 Assert(pfIntrState);
8495 Assert(!TRPMHasTrap(pVCpu));
8496
8497 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8498 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8499 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8500
8501 /*
8502 * Get the current interruptibility-state of the guest or nested-guest and
8503 * then figure out what needs to be injected.
8504 */
8505 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8506 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8507 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8508 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8509
8510 /* We don't support block-by-SMI yet.*/
8511 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8512
8513 /* Block-by-STI must not be set when interrupts are disabled. */
8514 if (fBlockSti)
8515 {
8516 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8517 Assert(pCtx->eflags.Bits.u1IF);
8518 }
8519
8520 /* Update interruptibility state to the caller. */
8521 *pfIntrState = fIntrState;
8522
8523 /*
8524 * Toggling of interrupt force-flags here is safe since we update TRPM on
8525 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8526 * We must NOT restore these force-flags.
8527 */
8528
8529 /** @todo SMI. SMIs take priority over NMIs. */
8530
8531 /*
8532 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8533 * NMIs take priority over external interrupts.
8534 */
8535 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8536 {
8537 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8538 if ( !pVCpu->hm.s.Event.fPending
8539 && !fBlockNmi
8540 && !fBlockSti
8541 && !fBlockMovSS)
8542 {
8543#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8544 if ( fIsNestedGuest
8545 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8546 return IEMExecVmxVmexitXcptNmi(pVCpu);
8547#endif
8548 hmR0VmxSetPendingXcptNmi(pVCpu);
8549 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8550 Log4Func(("Pending NMI\n"));
8551 }
8552 else if (!fIsNestedGuest)
8553 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8554 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8555 }
8556 /*
8557 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8558 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8559 * the interrupt. We can no longer re-request it from the APIC.
8560 */
8561 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8562 && !pVCpu->hm.s.fSingleInstruction)
8563 {
8564 Assert(!DBGFIsStepping(pVCpu));
8565 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8566 AssertRCReturn(rc, rc);
8567
8568 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8569 if ( !pVCpu->hm.s.Event.fPending
8570 && !fBlockInt
8571 && !fBlockSti
8572 && !fBlockMovSS)
8573 {
8574#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8575 if ( fIsNestedGuest
8576 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8577 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8578 {
8579 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8580 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8581 return rcStrict;
8582 }
8583#endif
8584 uint8_t u8Interrupt;
8585 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8586 if (RT_SUCCESS(rc))
8587 {
8588#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8589 if ( fIsNestedGuest
8590 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8591 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8592 {
8593 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8594 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8595 return rcStrict;
8596 }
8597#endif
8598 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8599 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8600 }
8601 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8602 {
8603 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8604
8605 if ( !fIsNestedGuest
8606 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8607 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8608 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8609
8610 /*
8611 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8612 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8613 * need to re-set this force-flag here.
8614 */
8615 }
8616 else
8617 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8618 }
8619 else if (!fIsNestedGuest)
8620 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8621 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8622 }
8623
8624 return VINF_SUCCESS;
8625}
8626
8627
8628/**
8629 * Injects any pending events into the guest if the guest is in a state to
8630 * receive them.
8631 *
8632 * @returns Strict VBox status code (i.e. informational status codes too).
8633 * @param pVCpu The cross context virtual CPU structure.
8634 * @param pVmxTransient The VMX-transient structure.
8635 * @param fIntrState The VT-x guest-interruptibility state.
8636 * @param fStepping Whether we are single-stepping the guest using the
8637 * hypervisor debugger and should return
8638 * VINF_EM_DBG_STEPPED if the event was dispatched
8639 * directly.
8640 */
8641static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8642{
8643 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8644 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8645
8646 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8647 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8648
8649 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8650 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8651 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8652 Assert(!TRPMHasTrap(pVCpu));
8653
8654 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8655 if (pVCpu->hm.s.Event.fPending)
8656 {
8657 /*
8658 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8659 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8660 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8661 *
8662 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8663 */
8664 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8665#ifdef VBOX_STRICT
8666 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8667 {
8668 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8669 Assert(!fBlockInt);
8670 Assert(!fBlockSti);
8671 Assert(!fBlockMovSS);
8672 }
8673 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8674 {
8675 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8676 Assert(!fBlockSti);
8677 Assert(!fBlockMovSS);
8678 Assert(!fBlockNmi);
8679 }
8680#endif
8681 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8682 uIntType));
8683
8684 /*
8685 * Inject the event and get any changes to the guest-interruptibility state.
8686 *
8687 * The guest-interruptibility state may need to be updated if we inject the event
8688 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8689 */
8690 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8691 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8692
8693 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8694 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8695 else
8696 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8697 }
8698
8699 /*
8700 * Update the guest-interruptibility state.
8701 *
8702 * This is required for the real-on-v86 software interrupt injection case above, as well as
8703 * updates to the guest state from ring-3 or IEM/REM.
8704 */
8705 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8706 AssertRC(rc);
8707
8708 /*
8709 * There's no need to clear the VM-entry interruption-information field here if we're not
8710 * injecting anything. VT-x clears the valid bit on every VM-exit.
8711 *
8712 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8713 */
8714
8715 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8716 NOREF(fBlockMovSS); NOREF(fBlockSti);
8717 return rcStrict;
8718}
8719
8720
8721/**
8722 * Enters the VT-x session.
8723 *
8724 * @returns VBox status code.
8725 * @param pVCpu The cross context virtual CPU structure.
8726 */
8727VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
8728{
8729 AssertPtr(pVCpu);
8730 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8731 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8732
8733 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8734 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8735 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8736
8737#ifdef VBOX_STRICT
8738 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8739 RTCCUINTREG uHostCr4 = ASMGetCR4();
8740 if (!(uHostCr4 & X86_CR4_VMXE))
8741 {
8742 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8743 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8744 }
8745#endif
8746
8747 /*
8748 * Load the appropriate VMCS as the current and active one.
8749 */
8750 PVMXVMCSINFO pVmcsInfo;
8751 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8752 if (!fInNestedGuestMode)
8753 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8754 else
8755 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8756 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8757 if (RT_SUCCESS(rc))
8758 {
8759 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8760 pVCpu->hm.s.fLeaveDone = false;
8761 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8762
8763 /*
8764 * Do the EMT scheduled L1D flush here if needed.
8765 */
8766 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8767 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8768 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8769 hmR0MdsClear();
8770 }
8771 return rc;
8772}
8773
8774
8775/**
8776 * The thread-context callback (only on platforms which support it).
8777 *
8778 * @param enmEvent The thread-context event.
8779 * @param pVCpu The cross context virtual CPU structure.
8780 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8781 * @thread EMT(pVCpu)
8782 */
8783VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
8784{
8785 AssertPtr(pVCpu);
8786 RT_NOREF1(fGlobalInit);
8787
8788 switch (enmEvent)
8789 {
8790 case RTTHREADCTXEVENT_OUT:
8791 {
8792 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8793 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8794 VMCPU_ASSERT_EMT(pVCpu);
8795
8796 /* No longjmps (logger flushes, locks) in this fragile context. */
8797 VMMRZCallRing3Disable(pVCpu);
8798 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8799
8800 /* Restore host-state (FPU, debug etc.) */
8801 if (!pVCpu->hm.s.fLeaveDone)
8802 {
8803 /*
8804 * Do -not- import the guest-state here as we might already be in the middle of importing
8805 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8806 */
8807 hmR0VmxLeave(pVCpu, false /* fImportState */);
8808 pVCpu->hm.s.fLeaveDone = true;
8809 }
8810
8811 /* Leave HM context, takes care of local init (term). */
8812 int rc = HMR0LeaveCpu(pVCpu);
8813 AssertRC(rc);
8814
8815 /* Restore longjmp state. */
8816 VMMRZCallRing3Enable(pVCpu);
8817 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8818 break;
8819 }
8820
8821 case RTTHREADCTXEVENT_IN:
8822 {
8823 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8824 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8825 VMCPU_ASSERT_EMT(pVCpu);
8826
8827 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8828 VMMRZCallRing3Disable(pVCpu);
8829 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8830
8831 /* Initialize the bare minimum state required for HM. This takes care of
8832 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8833 int rc = hmR0EnterCpu(pVCpu);
8834 AssertRC(rc);
8835 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8836 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8837
8838 /* Load the active VMCS as the current one. */
8839 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8840 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8841 AssertRC(rc);
8842 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8843 pVCpu->hm.s.fLeaveDone = false;
8844
8845 /* Do the EMT scheduled L1D flush if needed. */
8846 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8847 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8848
8849 /* Restore longjmp state. */
8850 VMMRZCallRing3Enable(pVCpu);
8851 break;
8852 }
8853
8854 default:
8855 break;
8856 }
8857}
8858
8859
8860/**
8861 * Exports the host state into the VMCS host-state area.
8862 * Sets up the VM-exit MSR-load area.
8863 *
8864 * The CPU state will be loaded from these fields on every successful VM-exit.
8865 *
8866 * @returns VBox status code.
8867 * @param pVCpu The cross context virtual CPU structure.
8868 *
8869 * @remarks No-long-jump zone!!!
8870 */
8871static int hmR0VmxExportHostState(PVMCPU pVCpu)
8872{
8873 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8874
8875 int rc = VINF_SUCCESS;
8876 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8877 {
8878 hmR0VmxExportHostControlRegs();
8879
8880 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8881 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8882
8883 hmR0VmxExportHostMsrs(pVCpu);
8884
8885 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8886 }
8887 return rc;
8888}
8889
8890
8891/**
8892 * Saves the host state in the VMCS host-state.
8893 *
8894 * @returns VBox status code.
8895 * @param pVCpu The cross context virtual CPU structure.
8896 *
8897 * @remarks No-long-jump zone!!!
8898 */
8899VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
8900{
8901 AssertPtr(pVCpu);
8902 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8903
8904 /*
8905 * Export the host state here while entering HM context.
8906 * When thread-context hooks are used, we might get preempted and have to re-save the host
8907 * state but most of the time we won't be, so do it here before we disable interrupts.
8908 */
8909 return hmR0VmxExportHostState(pVCpu);
8910}
8911
8912
8913/**
8914 * Exports the guest state into the VMCS guest-state area.
8915 *
8916 * The will typically be done before VM-entry when the guest-CPU state and the
8917 * VMCS state may potentially be out of sync.
8918 *
8919 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
8920 * VM-entry controls.
8921 * Sets up the appropriate VMX non-root function to execute guest code based on
8922 * the guest CPU mode.
8923 *
8924 * @returns VBox strict status code.
8925 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
8926 * without unrestricted guest execution and the VMMDev is not presently
8927 * mapped (e.g. EFI32).
8928 *
8929 * @param pVCpu The cross context virtual CPU structure.
8930 * @param pVmxTransient The VMX-transient structure.
8931 *
8932 * @remarks No-long-jump zone!!!
8933 */
8934static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
8935{
8936 AssertPtr(pVCpu);
8937 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8938 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8939
8940 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
8941
8942 /*
8943 * Determine real-on-v86 mode.
8944 * Used when the guest is in real-mode and unrestricted guest execution is not used.
8945 */
8946 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8947 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
8948 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
8949 pVmcsInfo->RealMode. fRealOnV86Active = false;
8950 else
8951 {
8952 Assert(!pVmxTransient->fIsNestedGuest);
8953 pVmcsInfo->RealMode.fRealOnV86Active = true;
8954 }
8955
8956 /*
8957 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
8958 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
8959 */
8960 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
8961 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
8962 * be a need to evaluate this everytime since I'm pretty sure we intercept
8963 * all guest paging mode changes. */
8964 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
8965 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8966
8967 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
8968 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8969
8970 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
8971 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8972
8973 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
8974 if (rcStrict == VINF_SUCCESS)
8975 { /* likely */ }
8976 else
8977 {
8978 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
8979 return rcStrict;
8980 }
8981
8982 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
8983 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8984
8985 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
8986 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8987
8988 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
8989 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8990
8991 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
8992 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8993
8994 rc = hmR0VmxExportGuestRip(pVCpu);
8995 rc |= hmR0VmxExportGuestRsp(pVCpu);
8996 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
8997 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8998
8999 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9000 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9001
9002 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9003 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9004 | HM_CHANGED_GUEST_CR2
9005 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9006 | HM_CHANGED_GUEST_X87
9007 | HM_CHANGED_GUEST_SSE_AVX
9008 | HM_CHANGED_GUEST_OTHER_XSAVE
9009 | HM_CHANGED_GUEST_XCRx
9010 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9011 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9012 | HM_CHANGED_GUEST_TSC_AUX
9013 | HM_CHANGED_GUEST_OTHER_MSRS
9014 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9015
9016 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9017 return rc;
9018}
9019
9020
9021/**
9022 * Exports the state shared between the host and guest into the VMCS.
9023 *
9024 * @param pVCpu The cross context virtual CPU structure.
9025 * @param pVmxTransient The VMX-transient structure.
9026 *
9027 * @remarks No-long-jump zone!!!
9028 */
9029static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9030{
9031 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9032 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9033
9034 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9035 {
9036 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9037 AssertRC(rc);
9038 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9039
9040 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9041 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9042 {
9043 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9044 AssertRC(rc);
9045 }
9046 }
9047
9048 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9049 {
9050 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9051 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9052 }
9053
9054 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9055 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9056}
9057
9058
9059/**
9060 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9061 *
9062 * @returns Strict VBox status code (i.e. informational status codes too).
9063 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9064 * without unrestricted guest execution and the VMMDev is not presently
9065 * mapped (e.g. EFI32).
9066 *
9067 * @param pVCpu The cross context virtual CPU structure.
9068 * @param pVmxTransient The VMX-transient structure.
9069 *
9070 * @remarks No-long-jump zone!!!
9071 */
9072static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9073{
9074 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9075 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9076 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9077
9078#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9079 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9080#endif
9081
9082 /*
9083 * For many exits it's only RIP that changes and hence try to export it first
9084 * without going through a lot of change flag checks.
9085 */
9086 VBOXSTRICTRC rcStrict;
9087 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9088 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9089 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9090 {
9091 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9092 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9093 { /* likely */}
9094 else
9095 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9096 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9097 }
9098 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9099 {
9100 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9101 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9102 { /* likely */}
9103 else
9104 {
9105 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9106 VBOXSTRICTRC_VAL(rcStrict)));
9107 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9108 return rcStrict;
9109 }
9110 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9111 }
9112 else
9113 rcStrict = VINF_SUCCESS;
9114
9115#ifdef VBOX_STRICT
9116 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9117 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9118 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9119 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9120 ("fCtxChanged=%#RX64\n", fCtxChanged));
9121#endif
9122 return rcStrict;
9123}
9124
9125
9126/**
9127 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9128 * and update error record fields accordingly.
9129 *
9130 * @returns VMX_IGS_* error codes.
9131 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9132 * wrong with the guest state.
9133 *
9134 * @param pVCpu The cross context virtual CPU structure.
9135 * @param pVmcsInfo The VMCS info. object.
9136 *
9137 * @remarks This function assumes our cache of the VMCS controls
9138 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9139 */
9140static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9141{
9142#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9143#define HMVMX_CHECK_BREAK(expr, err) do { \
9144 if (!(expr)) { uError = (err); break; } \
9145 } while (0)
9146
9147 int rc;
9148 PVM pVM = pVCpu->CTX_SUFF(pVM);
9149 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9150 uint32_t uError = VMX_IGS_ERROR;
9151 uint32_t u32Val;
9152 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9153
9154 do
9155 {
9156 /*
9157 * CR0.
9158 */
9159 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9160 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9161 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9162 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
9163 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9164 if (fUnrestrictedGuest)
9165 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9166
9167 uint64_t u64GuestCr0;
9168 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9169 AssertRC(rc);
9170 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9171 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9172 if ( !fUnrestrictedGuest
9173 && (u64GuestCr0 & X86_CR0_PG)
9174 && !(u64GuestCr0 & X86_CR0_PE))
9175 {
9176 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9177 }
9178
9179 /*
9180 * CR4.
9181 */
9182 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9183 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9184 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9185
9186 uint64_t u64GuestCr4;
9187 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9188 AssertRC(rc);
9189 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9190 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9191
9192 /*
9193 * IA32_DEBUGCTL MSR.
9194 */
9195 uint64_t u64Val;
9196 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9197 AssertRC(rc);
9198 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9199 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9200 {
9201 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9202 }
9203 uint64_t u64DebugCtlMsr = u64Val;
9204
9205#ifdef VBOX_STRICT
9206 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9207 AssertRC(rc);
9208 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9209#endif
9210 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9211
9212 /*
9213 * RIP and RFLAGS.
9214 */
9215 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9216 AssertRC(rc);
9217 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9218 if ( !fLongModeGuest
9219 || !pCtx->cs.Attr.n.u1Long)
9220 {
9221 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9222 }
9223 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9224 * must be identical if the "IA-32e mode guest" VM-entry
9225 * control is 1 and CS.L is 1. No check applies if the
9226 * CPU supports 64 linear-address bits. */
9227
9228 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9229 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9230 AssertRC(rc);
9231 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9232 VMX_IGS_RFLAGS_RESERVED);
9233 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9234 uint32_t const u32Eflags = u64Val;
9235
9236 if ( fLongModeGuest
9237 || ( fUnrestrictedGuest
9238 && !(u64GuestCr0 & X86_CR0_PE)))
9239 {
9240 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9241 }
9242
9243 uint32_t u32EntryInfo;
9244 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9245 AssertRC(rc);
9246 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9247 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9248
9249 /*
9250 * 64-bit checks.
9251 */
9252 if (fLongModeGuest)
9253 {
9254 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9255 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9256 }
9257
9258 if ( !fLongModeGuest
9259 && (u64GuestCr4 & X86_CR4_PCIDE))
9260 {
9261 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9262 }
9263
9264 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9265 * 51:32 beyond the processor's physical-address width are 0. */
9266
9267 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9268 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9269 {
9270 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9271 }
9272
9273 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9274 AssertRC(rc);
9275 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9276
9277 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9278 AssertRC(rc);
9279 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9280
9281 /*
9282 * PERF_GLOBAL MSR.
9283 */
9284 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9285 {
9286 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9287 AssertRC(rc);
9288 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9289 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9290 }
9291
9292 /*
9293 * PAT MSR.
9294 */
9295 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9296 {
9297 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9298 AssertRC(rc);
9299 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9300 for (unsigned i = 0; i < 8; i++)
9301 {
9302 uint8_t u8Val = (u64Val & 0xff);
9303 if ( u8Val != 0 /* UC */
9304 && u8Val != 1 /* WC */
9305 && u8Val != 4 /* WT */
9306 && u8Val != 5 /* WP */
9307 && u8Val != 6 /* WB */
9308 && u8Val != 7 /* UC- */)
9309 {
9310 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9311 }
9312 u64Val >>= 8;
9313 }
9314 }
9315
9316 /*
9317 * EFER MSR.
9318 */
9319 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9320 {
9321 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9322 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9323 AssertRC(rc);
9324 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9325 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9326 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9327 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9328 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9329 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9330 * iemVmxVmentryCheckGuestState(). */
9331 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9332 || !(u64GuestCr0 & X86_CR0_PG)
9333 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9334 VMX_IGS_EFER_LMA_LME_MISMATCH);
9335 }
9336
9337 /*
9338 * Segment registers.
9339 */
9340 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9341 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9342 if (!(u32Eflags & X86_EFL_VM))
9343 {
9344 /* CS */
9345 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9346 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9347 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9348 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9349 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9350 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9351 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9352 /* CS cannot be loaded with NULL in protected mode. */
9353 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9354 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9355 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9356 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9357 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9358 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9359 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9360 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9361 else
9362 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9363
9364 /* SS */
9365 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9366 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9367 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9368 if ( !(pCtx->cr0 & X86_CR0_PE)
9369 || pCtx->cs.Attr.n.u4Type == 3)
9370 {
9371 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9372 }
9373 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9374 {
9375 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9376 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9377 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9378 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9379 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9380 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9381 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9382 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9383 }
9384
9385 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9386 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9387 {
9388 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9389 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9390 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9391 || pCtx->ds.Attr.n.u4Type > 11
9392 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9393 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9394 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9395 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9396 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9397 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9398 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9399 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9400 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9401 }
9402 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9403 {
9404 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9405 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9406 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9407 || pCtx->es.Attr.n.u4Type > 11
9408 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9409 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9410 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9411 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9412 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9413 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9414 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9415 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9416 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9417 }
9418 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9419 {
9420 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9421 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9422 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9423 || pCtx->fs.Attr.n.u4Type > 11
9424 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9425 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9426 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9427 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9428 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9429 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9430 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9431 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9432 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9433 }
9434 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9435 {
9436 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9437 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9438 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9439 || pCtx->gs.Attr.n.u4Type > 11
9440 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9441 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9442 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9443 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9444 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9445 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9446 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9447 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9448 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9449 }
9450 /* 64-bit capable CPUs. */
9451 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9452 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9453 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9454 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9455 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9456 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9457 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9458 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9459 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9460 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9461 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9462 }
9463 else
9464 {
9465 /* V86 mode checks. */
9466 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9467 if (pVmcsInfo->RealMode.fRealOnV86Active)
9468 {
9469 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9470 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9471 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9472 }
9473 else
9474 {
9475 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9476 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9477 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9478 }
9479
9480 /* CS */
9481 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9482 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9483 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9484 /* SS */
9485 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9486 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9487 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9488 /* DS */
9489 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9490 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9491 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9492 /* ES */
9493 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9494 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9495 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9496 /* FS */
9497 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9498 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9499 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9500 /* GS */
9501 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9502 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9503 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9504 /* 64-bit capable CPUs. */
9505 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9506 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9507 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9508 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9509 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9510 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9511 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9512 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9513 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9514 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9515 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9516 }
9517
9518 /*
9519 * TR.
9520 */
9521 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9522 /* 64-bit capable CPUs. */
9523 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9524 if (fLongModeGuest)
9525 {
9526 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9527 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9528 }
9529 else
9530 {
9531 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9532 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9533 VMX_IGS_TR_ATTR_TYPE_INVALID);
9534 }
9535 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9536 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9537 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9538 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9539 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9540 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9541 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9542 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9543
9544 /*
9545 * GDTR and IDTR (64-bit capable checks).
9546 */
9547 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9548 AssertRC(rc);
9549 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9550
9551 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9552 AssertRC(rc);
9553 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9554
9555 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9556 AssertRC(rc);
9557 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9558
9559 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9560 AssertRC(rc);
9561 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9562
9563 /*
9564 * Guest Non-Register State.
9565 */
9566 /* Activity State. */
9567 uint32_t u32ActivityState;
9568 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9569 AssertRC(rc);
9570 HMVMX_CHECK_BREAK( !u32ActivityState
9571 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9572 VMX_IGS_ACTIVITY_STATE_INVALID);
9573 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9574 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9575 uint32_t u32IntrState;
9576 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9577 AssertRC(rc);
9578 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9579 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9580 {
9581 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9582 }
9583
9584 /** @todo Activity state and injecting interrupts. Left as a todo since we
9585 * currently don't use activity states but ACTIVE. */
9586
9587 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9588 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9589
9590 /* Guest interruptibility-state. */
9591 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9592 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9593 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9594 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9595 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9596 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9597 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9598 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9599 {
9600 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9601 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9602 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9603 }
9604 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9605 {
9606 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9607 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9608 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9609 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9610 }
9611 /** @todo Assumes the processor is not in SMM. */
9612 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9613 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9614 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9615 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9616 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9617 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9618 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9619 {
9620 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
9621 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9622 }
9623
9624 /* Pending debug exceptions. */
9625 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9626 AssertRC(rc);
9627 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9628 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9629 u32Val = u64Val; /* For pending debug exceptions checks below. */
9630
9631 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9632 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9633 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9634 {
9635 if ( (u32Eflags & X86_EFL_TF)
9636 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9637 {
9638 /* Bit 14 is PendingDebug.BS. */
9639 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9640 }
9641 if ( !(u32Eflags & X86_EFL_TF)
9642 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9643 {
9644 /* Bit 14 is PendingDebug.BS. */
9645 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9646 }
9647 }
9648
9649 /* VMCS link pointer. */
9650 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9651 AssertRC(rc);
9652 if (u64Val != UINT64_C(0xffffffffffffffff))
9653 {
9654 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9655 /** @todo Bits beyond the processor's physical-address width MBZ. */
9656 /** @todo SMM checks. */
9657 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9658 Assert(pVmcsInfo->pvShadowVmcs);
9659 VMXVMCSREVID VmcsRevId;
9660 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9661 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9662 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9663 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9664 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9665 }
9666
9667 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9668 * not using nested paging? */
9669 if ( pVM->hm.s.fNestedPaging
9670 && !fLongModeGuest
9671 && CPUMIsGuestInPAEModeEx(pCtx))
9672 {
9673 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9674 AssertRC(rc);
9675 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9676
9677 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9678 AssertRC(rc);
9679 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9680
9681 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9682 AssertRC(rc);
9683 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9684
9685 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9686 AssertRC(rc);
9687 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9688 }
9689
9690 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9691 if (uError == VMX_IGS_ERROR)
9692 uError = VMX_IGS_REASON_NOT_FOUND;
9693 } while (0);
9694
9695 pVCpu->hm.s.u32HMError = uError;
9696 return uError;
9697
9698#undef HMVMX_ERROR_BREAK
9699#undef HMVMX_CHECK_BREAK
9700}
9701
9702
9703/**
9704 * Map the APIC-access page for virtualizing APIC accesses.
9705 *
9706 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9707 * this not done as part of exporting guest state, see @bugref{8721}.
9708 *
9709 * @returns VBox status code.
9710 * @param pVCpu The cross context virtual CPU structure.
9711 */
9712static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
9713{
9714 PVM pVM = pVCpu->CTX_SUFF(pVM);
9715 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9716
9717 Assert(PDMHasApic(pVM));
9718 Assert(u64MsrApicBase);
9719
9720 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9721 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9722
9723 /* Unalias the existing mapping. */
9724 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9725 AssertRCReturn(rc, rc);
9726
9727 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9728 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9729 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9730 AssertRCReturn(rc, rc);
9731
9732 /* Update the per-VCPU cache of the APIC base MSR. */
9733 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9734 return VINF_SUCCESS;
9735}
9736
9737
9738/**
9739 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9740 * CPU.
9741 *
9742 * @param idCpu The ID for the CPU the function is called on.
9743 * @param pvUser1 Null, not used.
9744 * @param pvUser2 Null, not used.
9745 */
9746static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9747{
9748 RT_NOREF3(idCpu, pvUser1, pvUser2);
9749 VMXDispatchHostNmi();
9750}
9751
9752
9753/**
9754 * Dispatching an NMI on the host CPU that received it.
9755 *
9756 * @returns VBox status code.
9757 * @param pVCpu The cross context virtual CPU structure.
9758 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9759 * executing when receiving the host NMI in VMX non-root
9760 * operation.
9761 */
9762static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9763{
9764 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
9765
9766 /*
9767 * We don't want to delay dispatching the NMI any more than we have to. However,
9768 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9769 * after executing guest or nested-guest code for the following reasons:
9770 *
9771 * - We would need to perform VMREADs with interrupts disabled and is orders of
9772 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
9773 * supported by the host hypervisor.
9774 *
9775 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9776 * longer period of time just for handling an edge case like host NMIs which do
9777 * not occur nearly as frequently as other VM-exits.
9778 *
9779 * Let's cover the most likely scenario first. Check if we are on the target CPU
9780 * and dispatch the NMI right away. This should be much faster than calling into
9781 * RTMpOnSpecific() machinery.
9782 */
9783 bool fDispatched = false;
9784 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9785 if (idCpu == RTMpCpuId())
9786 {
9787 VMXDispatchHostNmi();
9788 fDispatched = true;
9789 }
9790 ASMSetFlags(fEFlags);
9791 if (fDispatched)
9792 {
9793 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9794 return VINF_SUCCESS;
9795 }
9796
9797 /*
9798 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9799 * there should be no race or recursion even if we are unlucky enough to be preempted
9800 * (to the target CPU) without dispatching the host NMI above.
9801 */
9802 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9803 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9804}
9805
9806
9807#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9808/**
9809 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9810 * nested-guest using hardware-assisted VMX.
9811 *
9812 * @param pVCpu The cross context virtual CPU structure.
9813 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9814 * @param pVmcsInfoGst The guest VMCS info. object.
9815 */
9816static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9817{
9818 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9819 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9820 Assert(pu64MsrBitmap);
9821
9822 /*
9823 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9824 * MSR that is intercepted by the guest is also intercepted while executing the
9825 * nested-guest using hardware-assisted VMX.
9826 *
9827 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9828 * nested-guest VM-exit even if the outer guest is not intercepting some
9829 * MSRs. We cannot assume the caller has initialized the nested-guest
9830 * MSR bitmap in this case.
9831 *
9832 * The guest hypervisor may also switch whether it uses MSR bitmaps for
9833 * each VM-entry, hence initializing it once per-VM while setting up the
9834 * nested-guest VMCS is not sufficient.
9835 */
9836 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9837 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9838 {
9839 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9840 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9841 Assert(pu64MsrBitmapNstGst);
9842 Assert(pu64MsrBitmapGst);
9843
9844 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9845 for (uint32_t i = 0; i < cFrags; i++)
9846 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9847 }
9848 else
9849 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9850}
9851
9852
9853/**
9854 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9855 * hardware-assisted VMX execution of the nested-guest.
9856 *
9857 * For a guest, we don't modify these controls once we set up the VMCS and hence
9858 * this function is never called.
9859 *
9860 * For nested-guests since the guest hypervisor provides these controls on every
9861 * nested-guest VM-entry and could potentially change them everytime we need to
9862 * merge them before every nested-guest VM-entry.
9863 *
9864 * @returns VBox status code.
9865 * @param pVCpu The cross context virtual CPU structure.
9866 */
9867static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
9868{
9869 PVM pVM = pVCpu->CTX_SUFF(pVM);
9870 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9871 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9872 Assert(pVmcsNstGst);
9873
9874 /*
9875 * Merge the controls with the requirements of the guest VMCS.
9876 *
9877 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9878 * VMCS with the features supported by the physical CPU as it's already done by the
9879 * VMLAUNCH/VMRESUME instruction emulation.
9880 *
9881 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9882 * derived from the VMX features supported by the physical CPU.
9883 */
9884
9885 /* Pin-based VM-execution controls. */
9886 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9887
9888 /* Processor-based VM-execution controls. */
9889 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9890 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9891 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9892 | VMX_PROC_CTLS_USE_TPR_SHADOW
9893 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9894
9895 /* Secondary processor-based VM-execution controls. */
9896 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9897 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9898 | VMX_PROC_CTLS2_INVPCID
9899 | VMX_PROC_CTLS2_VMCS_SHADOWING
9900 | VMX_PROC_CTLS2_RDTSCP
9901 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9902 | VMX_PROC_CTLS2_APIC_REG_VIRT
9903 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9904 | VMX_PROC_CTLS2_VMFUNC));
9905
9906 /*
9907 * VM-entry controls:
9908 * These controls contains state that depends on the nested-guest state (primarily
9909 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
9910 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
9911 * properly continue executing the nested-guest if the EFER MSR changes but does not
9912 * cause a nested-guest VM-exits.
9913 *
9914 * VM-exit controls:
9915 * These controls specify the host state on return. We cannot use the controls from
9916 * the guest hypervisor state as is as it would contain the guest state rather than
9917 * the host state. Since the host state is subject to change (e.g. preemption, trips
9918 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
9919 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
9920 *
9921 * VM-entry MSR-load:
9922 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
9923 * context by the VMLAUNCH/VMRESUME instruction emulation.
9924 *
9925 * VM-exit MSR-store:
9926 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
9927 * back into the VM-exit MSR-store area.
9928 *
9929 * VM-exit MSR-load areas:
9930 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
9931 * can entirely ignore what the guest hypervisor wants to load here.
9932 */
9933
9934 /*
9935 * Exception bitmap.
9936 *
9937 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
9938 * here (and avoid doing anything while exporting nested-guest state), but to keep the
9939 * code more flexible if intercepting exceptions become more dynamic in the future we do
9940 * it as part of exporting the nested-guest state.
9941 */
9942 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
9943
9944 /*
9945 * CR0/CR4 guest/host mask.
9946 *
9947 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
9948 * cause VM-exits, so we need to merge them here.
9949 */
9950 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
9951 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
9952
9953 /*
9954 * Page-fault error-code mask and match.
9955 *
9956 * Although we require unrestricted guest execution (and thereby nested-paging) for
9957 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
9958 * normally intercept #PFs, it might intercept them for debugging purposes.
9959 *
9960 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
9961 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
9962 */
9963 uint32_t u32XcptPFMask;
9964 uint32_t u32XcptPFMatch;
9965 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
9966 {
9967 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
9968 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
9969 }
9970 else
9971 {
9972 u32XcptPFMask = 0;
9973 u32XcptPFMatch = 0;
9974 }
9975
9976 /*
9977 * Pause-Loop exiting.
9978 */
9979 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
9980 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
9981
9982 /*
9983 * Pending debug exceptions.
9984 * Currently just copy whatever the nested-guest provides us.
9985 */
9986 uint64_t const uPendingDbgXcpt = pVmcsNstGst->u64GuestPendingDbgXcpt.u;
9987
9988 /*
9989 * I/O Bitmap.
9990 *
9991 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
9992 * intercept all I/O port accesses.
9993 */
9994 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
9995 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
9996
9997 /*
9998 * VMCS shadowing.
9999 *
10000 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10001 * enabled while executing the nested-guest.
10002 */
10003 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10004
10005 /*
10006 * APIC-access page.
10007 */
10008 RTHCPHYS HCPhysApicAccess;
10009 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10010 {
10011 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10012 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10013
10014 /** @todo NSTVMX: This is not really correct but currently is required to make
10015 * things work. We need to re-enable the page handler when we fallback to
10016 * IEM execution of the nested-guest! */
10017 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10018
10019 void *pvPage;
10020 PGMPAGEMAPLOCK PgLockApicAccess;
10021 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10022 if (RT_SUCCESS(rc))
10023 {
10024 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10025 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10026
10027 /** @todo Handle proper releasing of page-mapping lock later. */
10028 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10029 }
10030 else
10031 return rc;
10032 }
10033 else
10034 HCPhysApicAccess = 0;
10035
10036 /*
10037 * Virtual-APIC page and TPR threshold.
10038 */
10039 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10040 RTHCPHYS HCPhysVirtApic;
10041 uint32_t u32TprThreshold;
10042 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10043 {
10044 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10045 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10046
10047 void *pvPage;
10048 PGMPAGEMAPLOCK PgLockVirtApic;
10049 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10050 if (RT_SUCCESS(rc))
10051 {
10052 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10053 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10054
10055 /** @todo Handle proper releasing of page-mapping lock later. */
10056 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10057 }
10058 else
10059 return rc;
10060
10061 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10062 }
10063 else
10064 {
10065 HCPhysVirtApic = 0;
10066 u32TprThreshold = 0;
10067
10068 /*
10069 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10070 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10071 * be taken care of by EPT/shadow paging.
10072 */
10073 if (pVM->hm.s.fAllow64BitGuests)
10074 {
10075 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10076 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10077 }
10078 }
10079
10080 /*
10081 * Validate basic assumptions.
10082 */
10083 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10084 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10085 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10086
10087 /*
10088 * Commit it to the nested-guest VMCS.
10089 */
10090 int rc = VINF_SUCCESS;
10091 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10092 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10093 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10094 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10095 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10096 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10097 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10098 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10099 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10100 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10101 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10102 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10103 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10104 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10105 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10106 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10107 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10108 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10109 {
10110 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10111 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10112 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10113 }
10114 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10115 {
10116 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10117 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10118 }
10119 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10120 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10121 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpt);
10122 AssertRC(rc);
10123
10124 /*
10125 * Update the nested-guest VMCS cache.
10126 */
10127 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10128 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10129 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10130 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10131 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10132 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10133 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10134 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10135 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10136
10137 /*
10138 * We need to flush the TLB if we are switching the APIC-access page address.
10139 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10140 */
10141 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10142 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10143
10144 /*
10145 * MSR bitmap.
10146 *
10147 * The MSR bitmap address has already been initialized while setting up the nested-guest
10148 * VMCS, here we need to merge the MSR bitmaps.
10149 */
10150 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10151 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10152
10153 return VINF_SUCCESS;
10154}
10155#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10156
10157
10158/**
10159 * Does the preparations before executing guest code in VT-x.
10160 *
10161 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10162 * recompiler/IEM. We must be cautious what we do here regarding committing
10163 * guest-state information into the VMCS assuming we assuredly execute the
10164 * guest in VT-x mode.
10165 *
10166 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10167 * the common-state (TRPM/forceflags), we must undo those changes so that the
10168 * recompiler/IEM can (and should) use them when it resumes guest execution.
10169 * Otherwise such operations must be done when we can no longer exit to ring-3.
10170 *
10171 * @returns Strict VBox status code (i.e. informational status codes too).
10172 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10173 * have been disabled.
10174 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10175 * pending events).
10176 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10177 * double-fault into the guest.
10178 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10179 * dispatched directly.
10180 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10181 *
10182 * @param pVCpu The cross context virtual CPU structure.
10183 * @param pVmxTransient The VMX-transient structure.
10184 * @param fStepping Whether we are single-stepping the guest in the
10185 * hypervisor debugger. Makes us ignore some of the reasons
10186 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10187 * if event dispatching took place.
10188 */
10189static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10190{
10191 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10192
10193 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10194
10195#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10196 if (pVmxTransient->fIsNestedGuest)
10197 {
10198 RT_NOREF2(pVCpu, fStepping);
10199 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10200 return VINF_EM_RESCHEDULE_REM;
10201 }
10202#endif
10203
10204#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10205 PGMRZDynMapFlushAutoSet(pVCpu);
10206#endif
10207
10208 /*
10209 * Check and process force flag actions, some of which might require us to go back to ring-3.
10210 */
10211 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10212 if (rcStrict == VINF_SUCCESS)
10213 {
10214 /* FFs don't get set all the time. */
10215#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10216 if ( pVmxTransient->fIsNestedGuest
10217 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10218 {
10219 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10220 return VINF_VMX_VMEXIT;
10221 }
10222#endif
10223 }
10224 else
10225 return rcStrict;
10226
10227 /*
10228 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10229 */
10230 /** @todo Doing this from ring-3 after VM setup phase causes a
10231 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10232 * idea why atm. */
10233 PVM pVM = pVCpu->CTX_SUFF(pVM);
10234 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10235 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10236 && PDMHasApic(pVM))
10237 {
10238 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10239 AssertRCReturn(rc, rc);
10240 }
10241
10242#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10243 /*
10244 * Merge guest VMCS controls with the nested-guest VMCS controls.
10245 *
10246 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10247 * saved state), we should be okay with merging controls as we initialize the
10248 * guest VMCS controls as part of VM setup phase.
10249 */
10250 if ( pVmxTransient->fIsNestedGuest
10251 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10252 {
10253 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10254 AssertRCReturn(rc, rc);
10255 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10256 }
10257#endif
10258
10259 /*
10260 * Evaluate events to be injected into the guest.
10261 *
10262 * Events in TRPM can be injected without inspecting the guest state.
10263 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10264 * guest to cause a VM-exit the next time they are ready to receive the event.
10265 *
10266 * With nested-guests, evaluating pending events may cause VM-exits.
10267 */
10268 if (TRPMHasTrap(pVCpu))
10269 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10270
10271 uint32_t fIntrState;
10272 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10273
10274#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10275 /*
10276 * While evaluating pending events if something failed (unlikely) or if we were
10277 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10278 */
10279 if (rcStrict != VINF_SUCCESS)
10280 return rcStrict;
10281 if ( pVmxTransient->fIsNestedGuest
10282 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10283 {
10284 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10285 return VINF_VMX_VMEXIT;
10286 }
10287#else
10288 Assert(rcStrict == VINF_SUCCESS);
10289#endif
10290
10291 /*
10292 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10293 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10294 * also result in triple-faulting the VM.
10295 *
10296 * With nested-guests, the above does not apply since unrestricted guest execution is a
10297 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10298 */
10299 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10300 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10301 { /* likely */ }
10302 else
10303 {
10304 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10305 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10306 return rcStrict;
10307 }
10308
10309 /*
10310 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10311 * import CR3 themselves. We will need to update them here, as even as late as the above
10312 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10313 * the below force flags to be set.
10314 */
10315 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10316 {
10317 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10318 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10319 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10320 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10321 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10322 }
10323 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10324 {
10325 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10326 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10327 }
10328
10329#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10330 /* Paranoia. */
10331 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10332#endif
10333
10334 /*
10335 * No longjmps to ring-3 from this point on!!!
10336 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10337 * This also disables flushing of the R0-logger instance (if any).
10338 */
10339 VMMRZCallRing3Disable(pVCpu);
10340
10341 /*
10342 * Export the guest state bits.
10343 *
10344 * We cannot perform longjmps while loading the guest state because we do not preserve the
10345 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10346 * CPU migration.
10347 *
10348 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10349 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10350 */
10351 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10352 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10353 { /* likely */ }
10354 else
10355 {
10356 VMMRZCallRing3Enable(pVCpu);
10357 return rcStrict;
10358 }
10359
10360 /*
10361 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10362 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10363 * preemption disabled for a while. Since this is purely to aid the
10364 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10365 * disable interrupt on NT.
10366 *
10367 * We need to check for force-flags that could've possible been altered since we last
10368 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10369 * see @bugref{6398}).
10370 *
10371 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10372 * to ring-3 before executing guest code.
10373 */
10374 pVmxTransient->fEFlags = ASMIntDisableFlags();
10375
10376 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10377 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10378 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10379 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10380 {
10381 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10382 {
10383#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10384 /*
10385 * If we are executing a nested-guest make sure that we should intercept subsequent
10386 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10387 * the VM-exit instruction emulation happy.
10388 */
10389 if (pVmxTransient->fIsNestedGuest)
10390 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
10391#endif
10392
10393 /*
10394 * We've injected any pending events. This is really the point of no return (to ring-3).
10395 *
10396 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10397 * returns from this function, so do -not- enable them here.
10398 */
10399 pVCpu->hm.s.Event.fPending = false;
10400 return VINF_SUCCESS;
10401 }
10402
10403 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10404 rcStrict = VINF_EM_RAW_INTERRUPT;
10405 }
10406 else
10407 {
10408 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10409 rcStrict = VINF_EM_RAW_TO_R3;
10410 }
10411
10412 ASMSetFlags(pVmxTransient->fEFlags);
10413 VMMRZCallRing3Enable(pVCpu);
10414
10415 return rcStrict;
10416}
10417
10418
10419/**
10420 * Final preparations before executing guest code using hardware-assisted VMX.
10421 *
10422 * We can no longer get preempted to a different host CPU and there are no returns
10423 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10424 * failures), this function is not intended to fail sans unrecoverable hardware
10425 * errors.
10426 *
10427 * @param pVCpu The cross context virtual CPU structure.
10428 * @param pVmxTransient The VMX-transient structure.
10429 *
10430 * @remarks Called with preemption disabled.
10431 * @remarks No-long-jump zone!!!
10432 */
10433static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
10434{
10435 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10436 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10437 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10438 Assert(!pVCpu->hm.s.Event.fPending);
10439
10440 /*
10441 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10442 */
10443 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10444 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10445
10446 PVM pVM = pVCpu->CTX_SUFF(pVM);
10447 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10448 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10449 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10450
10451 if (!CPUMIsGuestFPUStateActive(pVCpu))
10452 {
10453 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10454 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10455 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10456 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10457 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10458 }
10459
10460 /*
10461 * Re-export the host state bits as we may've been preempted (only happens when
10462 * thread-context hooks are used or when the VM start function changes) or if
10463 * the host CR0 is modified while loading the guest FPU state above.
10464 *
10465 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10466 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10467 * see @bugref{8432}.
10468 *
10469 * This may also happen when switching to/from a nested-guest VMCS without leaving
10470 * ring-0.
10471 */
10472 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10473 {
10474 hmR0VmxExportHostState(pVCpu);
10475 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10476 }
10477 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10478
10479 /*
10480 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10481 */
10482 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10483 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10484 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10485
10486 /*
10487 * Store status of the shared guest/host debug state at the time of VM-entry.
10488 */
10489 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10490 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10491
10492 /*
10493 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10494 * more than one conditional check. The post-run side of our code shall determine
10495 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10496 */
10497 if (pVmcsInfo->pbVirtApic)
10498 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10499
10500 /*
10501 * Update the host MSRs values in the VM-exit MSR-load area.
10502 */
10503 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10504 {
10505 if (pVmcsInfo->cExitMsrLoad > 0)
10506 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10507 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10508 }
10509
10510 /*
10511 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10512 * VMX-preemption timer based on the next virtual sync clock deadline.
10513 */
10514 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10515 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10516 {
10517 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10518 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10519 }
10520
10521 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10522 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10523 if (!fIsRdtscIntercepted)
10524 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10525 else
10526 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10527
10528 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10529 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10530 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10531 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
10532 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
10533
10534 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10535
10536 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10537 as we're about to start executing the guest . */
10538
10539 /*
10540 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10541 *
10542 * This is done this late as updating the TSC offsetting/preemption timer above
10543 * figures out if we can skip intercepting RDTSCP by calculating the number of
10544 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10545 */
10546 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10547 && !fIsRdtscIntercepted)
10548 {
10549 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10550
10551 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10552 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10553 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10554 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10555 AssertRC(rc);
10556 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10557 pVmxTransient->fRemoveTscAuxMsr = true;
10558 }
10559
10560#ifdef VBOX_STRICT
10561 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10562 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10563 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10564 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10565#endif
10566
10567#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10568 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10569 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10570 * see @bugref{9180#c54}. */
10571 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10572 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10573 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10574#endif
10575}
10576
10577
10578/**
10579 * First C routine invoked after running guest code using hardware-assisted VMX.
10580 *
10581 * @param pVCpu The cross context virtual CPU structure.
10582 * @param pVmxTransient The VMX-transient structure.
10583 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10584 *
10585 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10586 *
10587 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10588 * unconditionally when it is safe to do so.
10589 */
10590static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10591{
10592 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10593
10594 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10595 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10596 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10597 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10598 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10599 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10600
10601 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10602 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10603 {
10604 uint64_t uGstTsc;
10605 if (!pVmxTransient->fIsNestedGuest)
10606 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10607 else
10608 {
10609 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10610 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10611 }
10612 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10613 }
10614
10615 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10616 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10617 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10618
10619 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10620 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10621#ifdef VBOX_STRICT
10622 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10623#endif
10624 Assert(!ASMIntAreEnabled());
10625 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10626 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10627
10628#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10629 /*
10630 * Clean all the VMCS fields in the transient structure before reading
10631 * anything from the VMCS.
10632 */
10633 pVmxTransient->uExitReason = 0;
10634 pVmxTransient->uExitIntErrorCode = 0;
10635 pVmxTransient->uExitQual = 0;
10636 pVmxTransient->uGuestLinearAddr = 0;
10637 pVmxTransient->uExitIntInfo = 0;
10638 pVmxTransient->cbInstr = 0;
10639 pVmxTransient->ExitInstrInfo.u = 0;
10640 pVmxTransient->uEntryIntInfo = 0;
10641 pVmxTransient->uEntryXcptErrorCode = 0;
10642 pVmxTransient->cbEntryInstr = 0;
10643 pVmxTransient->uIdtVectoringInfo = 0;
10644 pVmxTransient->uIdtVectoringErrorCode = 0;
10645#endif
10646
10647 /*
10648 * Save the basic VM-exit reason and check if the VM-entry failed.
10649 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10650 */
10651 uint32_t uExitReason;
10652 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10653 AssertRC(rc);
10654 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10655 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10656
10657 /*
10658 * Log the VM-exit before logging anything else as otherwise it might be a
10659 * tad confusing what happens before and after the world-switch.
10660 */
10661 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10662
10663 /*
10664 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10665 * bitmap permissions, if it was added before VM-entry.
10666 */
10667 if (pVmxTransient->fRemoveTscAuxMsr)
10668 {
10669 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10670 pVmxTransient->fRemoveTscAuxMsr = false;
10671 }
10672
10673 /*
10674 * Check if VMLAUNCH/VMRESUME succeeded.
10675 * If this failed, we cause a guru meditation and cease further execution.
10676 *
10677 * However, if we are executing a nested-guest we might fail if we use the
10678 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10679 */
10680 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10681 {
10682 /*
10683 * Update the VM-exit history array here even if the VM-entry failed due to:
10684 * - Invalid guest state.
10685 * - MSR loading.
10686 * - Machine-check event.
10687 *
10688 * In any of the above cases we will still have a "valid" VM-exit reason
10689 * despite @a fVMEntryFailed being false.
10690 *
10691 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10692 *
10693 * Note! We don't have CS or RIP at this point. Will probably address that later
10694 * by amending the history entry added here.
10695 */
10696 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10697 UINT64_MAX, uHostTsc);
10698
10699 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10700 {
10701 VMMRZCallRing3Enable(pVCpu);
10702
10703 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10704 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10705
10706#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10707 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10708#endif
10709#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10710 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10711 AssertRC(rc);
10712#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10713 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10714 AssertRC(rc);
10715#else
10716 /*
10717 * Import the guest-interruptibility state always as we need it while evaluating
10718 * injecting events on re-entry.
10719 *
10720 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10721 * checking for real-mode while exporting the state because all bits that cause
10722 * mode changes wrt CR0 are intercepted.
10723 */
10724 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10725 AssertRC(rc);
10726#endif
10727
10728 /*
10729 * Sync the TPR shadow with our APIC state.
10730 */
10731 if ( !pVmxTransient->fIsNestedGuest
10732 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10733 {
10734 Assert(pVmcsInfo->pbVirtApic);
10735 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10736 {
10737 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10738 AssertRC(rc);
10739 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10740 }
10741 }
10742
10743 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10744 return;
10745 }
10746 }
10747#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10748 else if (pVmxTransient->fIsNestedGuest)
10749 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10750#endif
10751 else
10752 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10753
10754 VMMRZCallRing3Enable(pVCpu);
10755}
10756
10757
10758/**
10759 * Runs the guest code using hardware-assisted VMX the normal way.
10760 *
10761 * @returns VBox status code.
10762 * @param pVCpu The cross context virtual CPU structure.
10763 * @param pcLoops Pointer to the number of executed loops.
10764 */
10765static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
10766{
10767 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10768 Assert(pcLoops);
10769 Assert(*pcLoops <= cMaxResumeLoops);
10770 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10771
10772#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10773 /*
10774 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10775 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10776 * guest VMCS while entering the VMX ring-0 session.
10777 */
10778 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10779 {
10780 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10781 if (RT_SUCCESS(rc))
10782 { /* likely */ }
10783 else
10784 {
10785 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10786 return rc;
10787 }
10788 }
10789#endif
10790
10791 VMXTRANSIENT VmxTransient;
10792 RT_ZERO(VmxTransient);
10793 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10794
10795 /* Paranoia. */
10796 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10797
10798 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10799 for (;;)
10800 {
10801 Assert(!HMR0SuspendPending());
10802 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10803 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10804
10805 /*
10806 * Preparatory work for running nested-guest code, this may force us to
10807 * return to ring-3.
10808 *
10809 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10810 */
10811 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10812 if (rcStrict != VINF_SUCCESS)
10813 break;
10814
10815 /* Interrupts are disabled at this point! */
10816 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10817 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10818 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10819 /* Interrupts are re-enabled at this point! */
10820
10821 /*
10822 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10823 */
10824 if (RT_SUCCESS(rcRun))
10825 { /* very likely */ }
10826 else
10827 {
10828 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10829 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10830 return rcRun;
10831 }
10832
10833 /*
10834 * Profile the VM-exit.
10835 */
10836 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10837 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10838 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10839 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10840 HMVMX_START_EXIT_DISPATCH_PROF();
10841
10842 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10843
10844 /*
10845 * Handle the VM-exit.
10846 */
10847#ifdef HMVMX_USE_FUNCTION_TABLE
10848 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10849#else
10850 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10851#endif
10852 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10853 if (rcStrict == VINF_SUCCESS)
10854 {
10855 if (++(*pcLoops) <= cMaxResumeLoops)
10856 continue;
10857 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10858 rcStrict = VINF_EM_RAW_INTERRUPT;
10859 }
10860 break;
10861 }
10862
10863 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10864 return rcStrict;
10865}
10866
10867
10868#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10869/**
10870 * Runs the nested-guest code using hardware-assisted VMX.
10871 *
10872 * @returns VBox status code.
10873 * @param pVCpu The cross context virtual CPU structure.
10874 * @param pcLoops Pointer to the number of executed loops.
10875 *
10876 * @sa hmR0VmxRunGuestCodeNormal.
10877 */
10878static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
10879{
10880 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10881 Assert(pcLoops);
10882 Assert(*pcLoops <= cMaxResumeLoops);
10883 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10884
10885 /*
10886 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10887 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10888 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10889 */
10890 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10891 {
10892 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10893 if (RT_SUCCESS(rc))
10894 { /* likely */ }
10895 else
10896 {
10897 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
10898 return rc;
10899 }
10900 }
10901
10902 VMXTRANSIENT VmxTransient;
10903 RT_ZERO(VmxTransient);
10904 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10905 VmxTransient.fIsNestedGuest = true;
10906
10907 /* Paranoia. */
10908 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10909
10910 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10911 for (;;)
10912 {
10913 Assert(!HMR0SuspendPending());
10914 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10915 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10916
10917 /*
10918 * Preparatory work for running guest code, this may force us to
10919 * return to ring-3.
10920 *
10921 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10922 */
10923 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10924 if (rcStrict != VINF_SUCCESS)
10925 break;
10926
10927 /* Interrupts are disabled at this point! */
10928 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10929 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10930 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10931 /* Interrupts are re-enabled at this point! */
10932
10933 /*
10934 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10935 */
10936 if (RT_SUCCESS(rcRun))
10937 { /* very likely */ }
10938 else
10939 {
10940 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10941 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10942 return rcRun;
10943 }
10944
10945 /*
10946 * Profile the VM-exit.
10947 */
10948 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10949 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10950 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
10951 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10952 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10953 HMVMX_START_EXIT_DISPATCH_PROF();
10954
10955 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10956
10957 /*
10958 * Handle the VM-exit.
10959 */
10960 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
10961 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10962 if (rcStrict == VINF_SUCCESS)
10963 {
10964 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10965 {
10966 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10967 rcStrict = VINF_VMX_VMEXIT;
10968 }
10969 else
10970 {
10971 if (++(*pcLoops) <= cMaxResumeLoops)
10972 continue;
10973 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10974 rcStrict = VINF_EM_RAW_INTERRUPT;
10975 }
10976 }
10977 else
10978 Assert(rcStrict != VINF_VMX_VMEXIT);
10979 break;
10980 }
10981
10982 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10983 return rcStrict;
10984}
10985#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10986
10987
10988/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
10989 * probes.
10990 *
10991 * The following few functions and associated structure contains the bloat
10992 * necessary for providing detailed debug events and dtrace probes as well as
10993 * reliable host side single stepping. This works on the principle of
10994 * "subclassing" the normal execution loop and workers. We replace the loop
10995 * method completely and override selected helpers to add necessary adjustments
10996 * to their core operation.
10997 *
10998 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
10999 * any performance for debug and analysis features.
11000 *
11001 * @{
11002 */
11003
11004/**
11005 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11006 * the debug run loop.
11007 */
11008typedef struct VMXRUNDBGSTATE
11009{
11010 /** The RIP we started executing at. This is for detecting that we stepped. */
11011 uint64_t uRipStart;
11012 /** The CS we started executing with. */
11013 uint16_t uCsStart;
11014
11015 /** Whether we've actually modified the 1st execution control field. */
11016 bool fModifiedProcCtls : 1;
11017 /** Whether we've actually modified the 2nd execution control field. */
11018 bool fModifiedProcCtls2 : 1;
11019 /** Whether we've actually modified the exception bitmap. */
11020 bool fModifiedXcptBitmap : 1;
11021
11022 /** We desire the modified the CR0 mask to be cleared. */
11023 bool fClearCr0Mask : 1;
11024 /** We desire the modified the CR4 mask to be cleared. */
11025 bool fClearCr4Mask : 1;
11026 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11027 uint32_t fCpe1Extra;
11028 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11029 uint32_t fCpe1Unwanted;
11030 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11031 uint32_t fCpe2Extra;
11032 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11033 uint32_t bmXcptExtra;
11034 /** The sequence number of the Dtrace provider settings the state was
11035 * configured against. */
11036 uint32_t uDtraceSettingsSeqNo;
11037 /** VM-exits to check (one bit per VM-exit). */
11038 uint32_t bmExitsToCheck[3];
11039
11040 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11041 uint32_t fProcCtlsInitial;
11042 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11043 uint32_t fProcCtls2Initial;
11044 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11045 uint32_t bmXcptInitial;
11046} VMXRUNDBGSTATE;
11047AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11048typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11049
11050
11051/**
11052 * Initializes the VMXRUNDBGSTATE structure.
11053 *
11054 * @param pVCpu The cross context virtual CPU structure of the
11055 * calling EMT.
11056 * @param pVmxTransient The VMX-transient structure.
11057 * @param pDbgState The debug state to initialize.
11058 */
11059static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11060{
11061 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11062 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11063
11064 pDbgState->fModifiedProcCtls = false;
11065 pDbgState->fModifiedProcCtls2 = false;
11066 pDbgState->fModifiedXcptBitmap = false;
11067 pDbgState->fClearCr0Mask = false;
11068 pDbgState->fClearCr4Mask = false;
11069 pDbgState->fCpe1Extra = 0;
11070 pDbgState->fCpe1Unwanted = 0;
11071 pDbgState->fCpe2Extra = 0;
11072 pDbgState->bmXcptExtra = 0;
11073 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11074 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11075 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11076}
11077
11078
11079/**
11080 * Updates the VMSC fields with changes requested by @a pDbgState.
11081 *
11082 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11083 * immediately before executing guest code, i.e. when interrupts are disabled.
11084 * We don't check status codes here as we cannot easily assert or return in the
11085 * latter case.
11086 *
11087 * @param pVCpu The cross context virtual CPU structure.
11088 * @param pVmxTransient The VMX-transient structure.
11089 * @param pDbgState The debug state.
11090 */
11091static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11092{
11093 /*
11094 * Ensure desired flags in VMCS control fields are set.
11095 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11096 *
11097 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11098 * there should be no stale data in pCtx at this point.
11099 */
11100 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11101 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11102 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11103 {
11104 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11105 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11106 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11107 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11108 pDbgState->fModifiedProcCtls = true;
11109 }
11110
11111 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11112 {
11113 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11114 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11115 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11116 pDbgState->fModifiedProcCtls2 = true;
11117 }
11118
11119 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11120 {
11121 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11122 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11123 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11124 pDbgState->fModifiedXcptBitmap = true;
11125 }
11126
11127 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11128 {
11129 pVmcsInfo->u64Cr0Mask = 0;
11130 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11131 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11132 }
11133
11134 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11135 {
11136 pVmcsInfo->u64Cr4Mask = 0;
11137 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11138 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11139 }
11140
11141 NOREF(pVCpu);
11142}
11143
11144
11145/**
11146 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11147 * re-entry next time around.
11148 *
11149 * @returns Strict VBox status code (i.e. informational status codes too).
11150 * @param pVCpu The cross context virtual CPU structure.
11151 * @param pVmxTransient The VMX-transient structure.
11152 * @param pDbgState The debug state.
11153 * @param rcStrict The return code from executing the guest using single
11154 * stepping.
11155 */
11156static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11157 VBOXSTRICTRC rcStrict)
11158{
11159 /*
11160 * Restore VM-exit control settings as we may not reenter this function the
11161 * next time around.
11162 */
11163 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11164
11165 /* We reload the initial value, trigger what we can of recalculations the
11166 next time around. From the looks of things, that's all that's required atm. */
11167 if (pDbgState->fModifiedProcCtls)
11168 {
11169 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11170 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11171 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11172 AssertRC(rc2);
11173 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11174 }
11175
11176 /* We're currently the only ones messing with this one, so just restore the
11177 cached value and reload the field. */
11178 if ( pDbgState->fModifiedProcCtls2
11179 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11180 {
11181 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11182 AssertRC(rc2);
11183 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11184 }
11185
11186 /* If we've modified the exception bitmap, we restore it and trigger
11187 reloading and partial recalculation the next time around. */
11188 if (pDbgState->fModifiedXcptBitmap)
11189 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11190
11191 return rcStrict;
11192}
11193
11194
11195/**
11196 * Configures VM-exit controls for current DBGF and DTrace settings.
11197 *
11198 * This updates @a pDbgState and the VMCS execution control fields to reflect
11199 * the necessary VM-exits demanded by DBGF and DTrace.
11200 *
11201 * @param pVCpu The cross context virtual CPU structure.
11202 * @param pVmxTransient The VMX-transient structure. May update
11203 * fUpdatedTscOffsettingAndPreemptTimer.
11204 * @param pDbgState The debug state.
11205 */
11206static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11207{
11208 /*
11209 * Take down the dtrace serial number so we can spot changes.
11210 */
11211 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11212 ASMCompilerBarrier();
11213
11214 /*
11215 * We'll rebuild most of the middle block of data members (holding the
11216 * current settings) as we go along here, so start by clearing it all.
11217 */
11218 pDbgState->bmXcptExtra = 0;
11219 pDbgState->fCpe1Extra = 0;
11220 pDbgState->fCpe1Unwanted = 0;
11221 pDbgState->fCpe2Extra = 0;
11222 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11223 pDbgState->bmExitsToCheck[i] = 0;
11224
11225 /*
11226 * Software interrupts (INT XXh) - no idea how to trigger these...
11227 */
11228 PVM pVM = pVCpu->CTX_SUFF(pVM);
11229 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11230 || VBOXVMM_INT_SOFTWARE_ENABLED())
11231 {
11232 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11233 }
11234
11235 /*
11236 * INT3 breakpoints - triggered by #BP exceptions.
11237 */
11238 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11239 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11240
11241 /*
11242 * Exception bitmap and XCPT events+probes.
11243 */
11244 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11245 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11246 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11247
11248 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11249 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11250 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11251 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11252 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11253 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11254 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11255 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11256 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11257 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11258 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11259 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11260 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11261 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11262 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11263 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11264 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11265 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11266
11267 if (pDbgState->bmXcptExtra)
11268 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11269
11270 /*
11271 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11272 *
11273 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11274 * So, when adding/changing/removing please don't forget to update it.
11275 *
11276 * Some of the macros are picking up local variables to save horizontal space,
11277 * (being able to see it in a table is the lesser evil here).
11278 */
11279#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11280 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11281 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11282#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11283 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11284 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11285 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11286 } else do { } while (0)
11287#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11288 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11289 { \
11290 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11291 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11292 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11293 } else do { } while (0)
11294#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11295 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11296 { \
11297 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11298 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11299 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11300 } else do { } while (0)
11301#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11302 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11303 { \
11304 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11305 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11306 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11307 } else do { } while (0)
11308
11309 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11310 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11311 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11312 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11313 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11314
11315 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11316 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11317 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11318 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11319 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11320 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11321 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11322 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11323 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11324 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11325 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11326 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11327 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11328 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11329 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11330 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11331 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11332 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11333 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11334 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11335 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11336 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11337 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11338 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11339 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11340 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11341 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11342 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11343 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11344 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11345 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11346 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11347 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11348 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11349 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11350 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11351
11352 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11353 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11354 {
11355 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11356 | CPUMCTX_EXTRN_APIC_TPR);
11357 AssertRC(rc);
11358
11359#if 0 /** @todo fix me */
11360 pDbgState->fClearCr0Mask = true;
11361 pDbgState->fClearCr4Mask = true;
11362#endif
11363 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11364 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11365 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11366 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11367 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11368 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11369 require clearing here and in the loop if we start using it. */
11370 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11371 }
11372 else
11373 {
11374 if (pDbgState->fClearCr0Mask)
11375 {
11376 pDbgState->fClearCr0Mask = false;
11377 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11378 }
11379 if (pDbgState->fClearCr4Mask)
11380 {
11381 pDbgState->fClearCr4Mask = false;
11382 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11383 }
11384 }
11385 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11386 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11387
11388 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11389 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11390 {
11391 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11392 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11393 }
11394 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11395 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11396
11397 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11398 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11399 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11400 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11401 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11402 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11403 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11404 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11405#if 0 /** @todo too slow, fix handler. */
11406 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11407#endif
11408 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11409
11410 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11411 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11412 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11413 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11414 {
11415 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11416 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11417 }
11418 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11419 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11420 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11421 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11422
11423 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11424 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11425 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11426 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11427 {
11428 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11429 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11430 }
11431 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11432 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11433 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11434 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11435
11436 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11437 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11438 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11439 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11440 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11441 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11442 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11443 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11444 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11445 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11446 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11447 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11448 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11449 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11450 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11451 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11452 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11453 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11454 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11455 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11456 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11457 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11458
11459#undef IS_EITHER_ENABLED
11460#undef SET_ONLY_XBM_IF_EITHER_EN
11461#undef SET_CPE1_XBM_IF_EITHER_EN
11462#undef SET_CPEU_XBM_IF_EITHER_EN
11463#undef SET_CPE2_XBM_IF_EITHER_EN
11464
11465 /*
11466 * Sanitize the control stuff.
11467 */
11468 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11469 if (pDbgState->fCpe2Extra)
11470 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11471 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11472 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11473 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11474 {
11475 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11476 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11477 }
11478
11479 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11480 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11481 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11482 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11483}
11484
11485
11486/**
11487 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11488 * appropriate.
11489 *
11490 * The caller has checked the VM-exit against the
11491 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11492 * already, so we don't have to do that either.
11493 *
11494 * @returns Strict VBox status code (i.e. informational status codes too).
11495 * @param pVCpu The cross context virtual CPU structure.
11496 * @param pVmxTransient The VMX-transient structure.
11497 * @param uExitReason The VM-exit reason.
11498 *
11499 * @remarks The name of this function is displayed by dtrace, so keep it short
11500 * and to the point. No longer than 33 chars long, please.
11501 */
11502static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11503{
11504 /*
11505 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11506 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11507 *
11508 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11509 * does. Must add/change/remove both places. Same ordering, please.
11510 *
11511 * Added/removed events must also be reflected in the next section
11512 * where we dispatch dtrace events.
11513 */
11514 bool fDtrace1 = false;
11515 bool fDtrace2 = false;
11516 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11517 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11518 uint32_t uEventArg = 0;
11519#define SET_EXIT(a_EventSubName) \
11520 do { \
11521 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11522 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11523 } while (0)
11524#define SET_BOTH(a_EventSubName) \
11525 do { \
11526 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11527 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11528 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11529 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11530 } while (0)
11531 switch (uExitReason)
11532 {
11533 case VMX_EXIT_MTF:
11534 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11535
11536 case VMX_EXIT_XCPT_OR_NMI:
11537 {
11538 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11539 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11540 {
11541 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11542 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11543 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11544 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11545 {
11546 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11547 {
11548 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11549 uEventArg = pVmxTransient->uExitIntErrorCode;
11550 }
11551 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11552 switch (enmEvent1)
11553 {
11554 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11555 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11556 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11557 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11558 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11559 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11560 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11561 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11562 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11563 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11564 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11565 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11566 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11567 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11568 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11569 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11570 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11571 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11572 default: break;
11573 }
11574 }
11575 else
11576 AssertFailed();
11577 break;
11578
11579 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11580 uEventArg = idxVector;
11581 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11582 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11583 break;
11584 }
11585 break;
11586 }
11587
11588 case VMX_EXIT_TRIPLE_FAULT:
11589 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11590 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11591 break;
11592 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11593 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11594 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11595 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11596 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11597
11598 /* Instruction specific VM-exits: */
11599 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11600 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11601 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11602 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11603 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11604 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11605 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11606 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11607 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11608 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11609 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11610 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11611 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11612 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11613 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11614 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11615 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11616 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11617 case VMX_EXIT_MOV_CRX:
11618 hmR0VmxReadExitQualVmcs(pVmxTransient);
11619 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11620 SET_BOTH(CRX_READ);
11621 else
11622 SET_BOTH(CRX_WRITE);
11623 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11624 break;
11625 case VMX_EXIT_MOV_DRX:
11626 hmR0VmxReadExitQualVmcs(pVmxTransient);
11627 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11628 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11629 SET_BOTH(DRX_READ);
11630 else
11631 SET_BOTH(DRX_WRITE);
11632 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11633 break;
11634 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11635 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11636 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11637 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11638 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11639 case VMX_EXIT_GDTR_IDTR_ACCESS:
11640 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11641 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11642 {
11643 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11644 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11645 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11646 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11647 }
11648 break;
11649
11650 case VMX_EXIT_LDTR_TR_ACCESS:
11651 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11652 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11653 {
11654 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11655 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11656 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11657 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11658 }
11659 break;
11660
11661 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11662 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11663 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11664 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11665 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11666 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11667 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11668 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11669 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11670 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11671 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11672
11673 /* Events that aren't relevant at this point. */
11674 case VMX_EXIT_EXT_INT:
11675 case VMX_EXIT_INT_WINDOW:
11676 case VMX_EXIT_NMI_WINDOW:
11677 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11678 case VMX_EXIT_PREEMPT_TIMER:
11679 case VMX_EXIT_IO_INSTR:
11680 break;
11681
11682 /* Errors and unexpected events. */
11683 case VMX_EXIT_INIT_SIGNAL:
11684 case VMX_EXIT_SIPI:
11685 case VMX_EXIT_IO_SMI:
11686 case VMX_EXIT_SMI:
11687 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11688 case VMX_EXIT_ERR_MSR_LOAD:
11689 case VMX_EXIT_ERR_MACHINE_CHECK:
11690 case VMX_EXIT_PML_FULL:
11691 case VMX_EXIT_VIRTUALIZED_EOI:
11692 break;
11693
11694 default:
11695 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11696 break;
11697 }
11698#undef SET_BOTH
11699#undef SET_EXIT
11700
11701 /*
11702 * Dtrace tracepoints go first. We do them here at once so we don't
11703 * have to copy the guest state saving and stuff a few dozen times.
11704 * Down side is that we've got to repeat the switch, though this time
11705 * we use enmEvent since the probes are a subset of what DBGF does.
11706 */
11707 if (fDtrace1 || fDtrace2)
11708 {
11709 hmR0VmxReadExitQualVmcs(pVmxTransient);
11710 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11711 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11712 switch (enmEvent1)
11713 {
11714 /** @todo consider which extra parameters would be helpful for each probe. */
11715 case DBGFEVENT_END: break;
11716 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11717 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11718 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11719 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11720 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11721 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11722 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11723 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11724 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11725 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11726 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11727 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11728 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11729 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11730 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11731 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11732 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11733 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11734 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11735 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11736 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11737 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11738 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11739 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11740 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11741 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11742 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11743 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11744 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11745 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11746 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11747 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11748 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11749 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11750 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11751 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11752 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11753 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11754 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11755 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11756 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11757 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11758 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11759 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11760 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11761 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11762 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11763 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11764 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11765 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11766 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11767 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11768 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11769 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11770 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11771 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11772 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11773 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11774 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11775 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11776 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11777 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11778 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11779 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11780 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11781 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11782 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11783 }
11784 switch (enmEvent2)
11785 {
11786 /** @todo consider which extra parameters would be helpful for each probe. */
11787 case DBGFEVENT_END: break;
11788 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11789 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11790 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11791 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11792 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11793 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11794 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11795 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11796 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11797 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11798 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11799 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11800 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11801 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11802 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11803 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11804 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11805 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11806 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11807 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11808 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11809 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11810 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11811 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11812 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11813 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11814 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11815 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11816 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11817 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11818 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11819 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11820 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11821 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11822 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11823 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11824 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11825 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11826 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11827 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11828 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11829 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11830 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11831 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11832 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11833 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11834 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11835 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11836 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11837 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11838 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11839 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11840 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11841 }
11842 }
11843
11844 /*
11845 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11846 * the DBGF call will do a full check).
11847 *
11848 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11849 * Note! If we have to events, we prioritize the first, i.e. the instruction
11850 * one, in order to avoid event nesting.
11851 */
11852 PVM pVM = pVCpu->CTX_SUFF(pVM);
11853 if ( enmEvent1 != DBGFEVENT_END
11854 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11855 {
11856 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11857 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11858 if (rcStrict != VINF_SUCCESS)
11859 return rcStrict;
11860 }
11861 else if ( enmEvent2 != DBGFEVENT_END
11862 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11863 {
11864 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11865 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11866 if (rcStrict != VINF_SUCCESS)
11867 return rcStrict;
11868 }
11869
11870 return VINF_SUCCESS;
11871}
11872
11873
11874/**
11875 * Single-stepping VM-exit filtering.
11876 *
11877 * This is preprocessing the VM-exits and deciding whether we've gotten far
11878 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11879 * handling is performed.
11880 *
11881 * @returns Strict VBox status code (i.e. informational status codes too).
11882 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11883 * @param pVmxTransient The VMX-transient structure.
11884 * @param pDbgState The debug state.
11885 */
11886DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11887{
11888 /*
11889 * Expensive (saves context) generic dtrace VM-exit probe.
11890 */
11891 uint32_t const uExitReason = pVmxTransient->uExitReason;
11892 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11893 { /* more likely */ }
11894 else
11895 {
11896 hmR0VmxReadExitQualVmcs(pVmxTransient);
11897 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11898 AssertRC(rc);
11899 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11900 }
11901
11902 /*
11903 * Check for host NMI, just to get that out of the way.
11904 */
11905 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11906 { /* normally likely */ }
11907 else
11908 {
11909 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11910 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
11911 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
11912 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
11913 }
11914
11915 /*
11916 * Check for single stepping event if we're stepping.
11917 */
11918 if (pVCpu->hm.s.fSingleInstruction)
11919 {
11920 switch (uExitReason)
11921 {
11922 case VMX_EXIT_MTF:
11923 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11924
11925 /* Various events: */
11926 case VMX_EXIT_XCPT_OR_NMI:
11927 case VMX_EXIT_EXT_INT:
11928 case VMX_EXIT_TRIPLE_FAULT:
11929 case VMX_EXIT_INT_WINDOW:
11930 case VMX_EXIT_NMI_WINDOW:
11931 case VMX_EXIT_TASK_SWITCH:
11932 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11933 case VMX_EXIT_APIC_ACCESS:
11934 case VMX_EXIT_EPT_VIOLATION:
11935 case VMX_EXIT_EPT_MISCONFIG:
11936 case VMX_EXIT_PREEMPT_TIMER:
11937
11938 /* Instruction specific VM-exits: */
11939 case VMX_EXIT_CPUID:
11940 case VMX_EXIT_GETSEC:
11941 case VMX_EXIT_HLT:
11942 case VMX_EXIT_INVD:
11943 case VMX_EXIT_INVLPG:
11944 case VMX_EXIT_RDPMC:
11945 case VMX_EXIT_RDTSC:
11946 case VMX_EXIT_RSM:
11947 case VMX_EXIT_VMCALL:
11948 case VMX_EXIT_VMCLEAR:
11949 case VMX_EXIT_VMLAUNCH:
11950 case VMX_EXIT_VMPTRLD:
11951 case VMX_EXIT_VMPTRST:
11952 case VMX_EXIT_VMREAD:
11953 case VMX_EXIT_VMRESUME:
11954 case VMX_EXIT_VMWRITE:
11955 case VMX_EXIT_VMXOFF:
11956 case VMX_EXIT_VMXON:
11957 case VMX_EXIT_MOV_CRX:
11958 case VMX_EXIT_MOV_DRX:
11959 case VMX_EXIT_IO_INSTR:
11960 case VMX_EXIT_RDMSR:
11961 case VMX_EXIT_WRMSR:
11962 case VMX_EXIT_MWAIT:
11963 case VMX_EXIT_MONITOR:
11964 case VMX_EXIT_PAUSE:
11965 case VMX_EXIT_GDTR_IDTR_ACCESS:
11966 case VMX_EXIT_LDTR_TR_ACCESS:
11967 case VMX_EXIT_INVEPT:
11968 case VMX_EXIT_RDTSCP:
11969 case VMX_EXIT_INVVPID:
11970 case VMX_EXIT_WBINVD:
11971 case VMX_EXIT_XSETBV:
11972 case VMX_EXIT_RDRAND:
11973 case VMX_EXIT_INVPCID:
11974 case VMX_EXIT_VMFUNC:
11975 case VMX_EXIT_RDSEED:
11976 case VMX_EXIT_XSAVES:
11977 case VMX_EXIT_XRSTORS:
11978 {
11979 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11980 AssertRCReturn(rc, rc);
11981 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
11982 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
11983 return VINF_EM_DBG_STEPPED;
11984 break;
11985 }
11986
11987 /* Errors and unexpected events: */
11988 case VMX_EXIT_INIT_SIGNAL:
11989 case VMX_EXIT_SIPI:
11990 case VMX_EXIT_IO_SMI:
11991 case VMX_EXIT_SMI:
11992 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11993 case VMX_EXIT_ERR_MSR_LOAD:
11994 case VMX_EXIT_ERR_MACHINE_CHECK:
11995 case VMX_EXIT_PML_FULL:
11996 case VMX_EXIT_VIRTUALIZED_EOI:
11997 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
11998 break;
11999
12000 default:
12001 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12002 break;
12003 }
12004 }
12005
12006 /*
12007 * Check for debugger event breakpoints and dtrace probes.
12008 */
12009 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12010 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12011 {
12012 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12013 if (rcStrict != VINF_SUCCESS)
12014 return rcStrict;
12015 }
12016
12017 /*
12018 * Normal processing.
12019 */
12020#ifdef HMVMX_USE_FUNCTION_TABLE
12021 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12022#else
12023 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12024#endif
12025}
12026
12027
12028/**
12029 * Single steps guest code using hardware-assisted VMX.
12030 *
12031 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12032 * but single-stepping through the hypervisor debugger.
12033 *
12034 * @returns Strict VBox status code (i.e. informational status codes too).
12035 * @param pVCpu The cross context virtual CPU structure.
12036 * @param pcLoops Pointer to the number of executed loops.
12037 *
12038 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12039 */
12040static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12041{
12042 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12043 Assert(pcLoops);
12044 Assert(*pcLoops <= cMaxResumeLoops);
12045
12046 VMXTRANSIENT VmxTransient;
12047 RT_ZERO(VmxTransient);
12048 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12049
12050 /* Set HMCPU indicators. */
12051 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12052 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12053 pVCpu->hm.s.fDebugWantRdTscExit = false;
12054 pVCpu->hm.s.fUsingDebugLoop = true;
12055
12056 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12057 VMXRUNDBGSTATE DbgState;
12058 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12059 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12060
12061 /*
12062 * The loop.
12063 */
12064 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12065 for (;;)
12066 {
12067 Assert(!HMR0SuspendPending());
12068 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12069 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12070 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12071
12072 /* Set up VM-execution controls the next two can respond to. */
12073 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12074
12075 /*
12076 * Preparatory work for running guest code, this may force us to
12077 * return to ring-3.
12078 *
12079 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12080 */
12081 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12082 if (rcStrict != VINF_SUCCESS)
12083 break;
12084
12085 /* Interrupts are disabled at this point! */
12086 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12087
12088 /* Override any obnoxious code in the above two calls. */
12089 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12090
12091 /*
12092 * Finally execute the guest.
12093 */
12094 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12095
12096 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12097 /* Interrupts are re-enabled at this point! */
12098
12099 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12100 if (RT_SUCCESS(rcRun))
12101 { /* very likely */ }
12102 else
12103 {
12104 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12105 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12106 return rcRun;
12107 }
12108
12109 /* Profile the VM-exit. */
12110 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12111 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12112 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12113 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12114 HMVMX_START_EXIT_DISPATCH_PROF();
12115
12116 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12117
12118 /*
12119 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12120 */
12121 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12122 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12123 if (rcStrict != VINF_SUCCESS)
12124 break;
12125 if (++(*pcLoops) > cMaxResumeLoops)
12126 {
12127 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12128 rcStrict = VINF_EM_RAW_INTERRUPT;
12129 break;
12130 }
12131
12132 /*
12133 * Stepping: Did the RIP change, if so, consider it a single step.
12134 * Otherwise, make sure one of the TFs gets set.
12135 */
12136 if (fStepping)
12137 {
12138 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12139 AssertRC(rc);
12140 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12141 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12142 {
12143 rcStrict = VINF_EM_DBG_STEPPED;
12144 break;
12145 }
12146 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12147 }
12148
12149 /*
12150 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12151 */
12152 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12153 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12154 }
12155
12156 /*
12157 * Clear the X86_EFL_TF if necessary.
12158 */
12159 if (pVCpu->hm.s.fClearTrapFlag)
12160 {
12161 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12162 AssertRC(rc);
12163 pVCpu->hm.s.fClearTrapFlag = false;
12164 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12165 }
12166 /** @todo there seems to be issues with the resume flag when the monitor trap
12167 * flag is pending without being used. Seen early in bios init when
12168 * accessing APIC page in protected mode. */
12169
12170 /*
12171 * Restore VM-exit control settings as we may not re-enter this function the
12172 * next time around.
12173 */
12174 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12175
12176 /* Restore HMCPU indicators. */
12177 pVCpu->hm.s.fUsingDebugLoop = false;
12178 pVCpu->hm.s.fDebugWantRdTscExit = false;
12179 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12180
12181 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12182 return rcStrict;
12183}
12184
12185
12186/** @} */
12187
12188
12189/**
12190 * Checks if any expensive dtrace probes are enabled and we should go to the
12191 * debug loop.
12192 *
12193 * @returns true if we should use debug loop, false if not.
12194 */
12195static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12196{
12197 /* It's probably faster to OR the raw 32-bit counter variables together.
12198 Since the variables are in an array and the probes are next to one
12199 another (more or less), we have good locality. So, better read
12200 eight-nine cache lines ever time and only have one conditional, than
12201 128+ conditionals, right? */
12202 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12203 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12204 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12205 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12206 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12207 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12208 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12209 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12210 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12211 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12212 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12213 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12214 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12215 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12216 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12217 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12218 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12219 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12220 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12221 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12222 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12223 ) != 0
12224 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12225 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12226 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12227 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12228 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12229 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12230 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12231 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12232 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12233 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12234 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12235 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12236 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12237 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12238 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12239 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12240 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12241 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12242 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12243 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12244 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12245 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12246 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12247 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12248 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12249 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12250 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12251 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12252 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12253 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12254 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12255 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12256 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12257 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12258 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12259 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12260 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12261 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12262 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12263 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12264 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12265 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12266 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12267 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12268 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12269 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12270 ) != 0
12271 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12272 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12273 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12274 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12275 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12276 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12277 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12278 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12279 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12280 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12281 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12282 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12283 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12284 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12285 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12286 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12287 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12288 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12289 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12290 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12291 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12292 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12293 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12294 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12295 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12296 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12297 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12298 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12299 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12300 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12301 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12302 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12303 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12304 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12305 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12306 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12307 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12308 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12309 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12310 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12311 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12312 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12313 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12314 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12315 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12316 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12317 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12318 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12319 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12320 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12321 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12322 ) != 0;
12323}
12324
12325
12326/**
12327 * Runs the guest using hardware-assisted VMX.
12328 *
12329 * @returns Strict VBox status code (i.e. informational status codes too).
12330 * @param pVCpu The cross context virtual CPU structure.
12331 */
12332VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
12333{
12334 AssertPtr(pVCpu);
12335 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12336 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12337 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12338 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12339
12340 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
12341
12342 VBOXSTRICTRC rcStrict;
12343 uint32_t cLoops = 0;
12344 for (;;)
12345 {
12346#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12347 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12348#else
12349 bool const fInNestedGuestMode = false;
12350#endif
12351 if (!fInNestedGuestMode)
12352 {
12353 if ( !pVCpu->hm.s.fUseDebugLoop
12354 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12355 && !DBGFIsStepping(pVCpu)
12356 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12357 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12358 else
12359 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12360 }
12361#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12362 else
12363 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12364
12365 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12366 {
12367 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12368 continue;
12369 }
12370 if (rcStrict == VINF_VMX_VMEXIT)
12371 {
12372 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12373 continue;
12374 }
12375#endif
12376 break;
12377 }
12378
12379 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12380 switch (rcLoop)
12381 {
12382 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12383 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12384 }
12385
12386 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12387 if (RT_FAILURE(rc2))
12388 {
12389 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12390 rcStrict = rc2;
12391 }
12392 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12393 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12394 return rcStrict;
12395}
12396
12397
12398#ifndef HMVMX_USE_FUNCTION_TABLE
12399/**
12400 * Handles a guest VM-exit from hardware-assisted VMX execution.
12401 *
12402 * @returns Strict VBox status code (i.e. informational status codes too).
12403 * @param pVCpu The cross context virtual CPU structure.
12404 * @param pVmxTransient The VMX-transient structure.
12405 */
12406DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12407{
12408#ifdef DEBUG_ramshankar
12409#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12410 do { \
12411 if (a_fSave != 0) \
12412 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12413 VBOXSTRICTRC rcStrict = a_CallExpr; \
12414 if (a_fSave != 0) \
12415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12416 return rcStrict; \
12417 } while (0)
12418#else
12419# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12420#endif
12421 uint32_t const uExitReason = pVmxTransient->uExitReason;
12422 switch (uExitReason)
12423 {
12424 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12425 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12426 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12427 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12428 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12429 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12430 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12431 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12432 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12433 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12434 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12435 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12436 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12437 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12438 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12439 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12440 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12441 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12442 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12443 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12444 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12445 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12446 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12447 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12448 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12449 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12450 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12451 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12452 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12453 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12454#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12455 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12456 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12457 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12458 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12459 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12460 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12461 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12462 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12463 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12464 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12465 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12466#else
12467 case VMX_EXIT_VMCLEAR:
12468 case VMX_EXIT_VMLAUNCH:
12469 case VMX_EXIT_VMPTRLD:
12470 case VMX_EXIT_VMPTRST:
12471 case VMX_EXIT_VMREAD:
12472 case VMX_EXIT_VMRESUME:
12473 case VMX_EXIT_VMWRITE:
12474 case VMX_EXIT_VMXOFF:
12475 case VMX_EXIT_VMXON:
12476 case VMX_EXIT_INVVPID:
12477 case VMX_EXIT_INVEPT:
12478 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12479#endif
12480
12481 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12482 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12483 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12484
12485 case VMX_EXIT_INIT_SIGNAL:
12486 case VMX_EXIT_SIPI:
12487 case VMX_EXIT_IO_SMI:
12488 case VMX_EXIT_SMI:
12489 case VMX_EXIT_ERR_MSR_LOAD:
12490 case VMX_EXIT_ERR_MACHINE_CHECK:
12491 case VMX_EXIT_PML_FULL:
12492 case VMX_EXIT_VIRTUALIZED_EOI:
12493 case VMX_EXIT_GDTR_IDTR_ACCESS:
12494 case VMX_EXIT_LDTR_TR_ACCESS:
12495 case VMX_EXIT_APIC_WRITE:
12496 case VMX_EXIT_RDRAND:
12497 case VMX_EXIT_RSM:
12498 case VMX_EXIT_VMFUNC:
12499 case VMX_EXIT_ENCLS:
12500 case VMX_EXIT_RDSEED:
12501 case VMX_EXIT_XSAVES:
12502 case VMX_EXIT_XRSTORS:
12503 case VMX_EXIT_UMWAIT:
12504 case VMX_EXIT_TPAUSE:
12505 default:
12506 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12507 }
12508#undef VMEXIT_CALL_RET
12509}
12510#endif /* !HMVMX_USE_FUNCTION_TABLE */
12511
12512
12513#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12514/**
12515 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12516 *
12517 * @returns Strict VBox status code (i.e. informational status codes too).
12518 * @param pVCpu The cross context virtual CPU structure.
12519 * @param pVmxTransient The VMX-transient structure.
12520 */
12521DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12522{
12523 /** @todo NSTVMX: Remove after debugging regression. */
12524#if 1 //def DEBUG_ramshankar Remove later
12525 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP);
12526 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.rsp));
12527#endif
12528
12529 uint32_t const uExitReason = pVmxTransient->uExitReason;
12530 switch (uExitReason)
12531 {
12532 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12533 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12534 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12535 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12536 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12537
12538 /*
12539 * We shouldn't direct host physical interrupts to the nested-guest.
12540 */
12541 case VMX_EXIT_EXT_INT:
12542 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12543
12544 /*
12545 * Instructions that cause VM-exits unconditionally or the condition is
12546 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12547 * happens, it's guaranteed to be a nested-guest VM-exit).
12548 *
12549 * - Provides VM-exit instruction length ONLY.
12550 */
12551 case VMX_EXIT_CPUID: /* Unconditional. */
12552 case VMX_EXIT_VMCALL:
12553 case VMX_EXIT_GETSEC:
12554 case VMX_EXIT_INVD:
12555 case VMX_EXIT_XSETBV:
12556 case VMX_EXIT_VMLAUNCH:
12557 case VMX_EXIT_VMRESUME:
12558 case VMX_EXIT_VMXOFF:
12559 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
12560 case VMX_EXIT_VMFUNC:
12561 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12562
12563 /*
12564 * Instructions that cause VM-exits unconditionally or the condition is
12565 * always is taken solely from the guest hypervisor (meaning if the VM-exit
12566 * happens, it's guaranteed to be a nested-guest VM-exit).
12567 *
12568 * - Provides VM-exit instruction length.
12569 * - Provides VM-exit information.
12570 * - Optionally provides Exit qualification.
12571 *
12572 * Since Exit qualification is 0 for all VM-exits where it is not
12573 * applicable, reading and passing it to the guest should produce
12574 * defined behavior.
12575 *
12576 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12577 */
12578 case VMX_EXIT_INVEPT: /* Unconditional. */
12579 case VMX_EXIT_INVVPID:
12580 case VMX_EXIT_VMCLEAR:
12581 case VMX_EXIT_VMPTRLD:
12582 case VMX_EXIT_VMPTRST:
12583 case VMX_EXIT_VMXON:
12584 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
12585 case VMX_EXIT_LDTR_TR_ACCESS:
12586 case VMX_EXIT_RDRAND:
12587 case VMX_EXIT_RDSEED:
12588 case VMX_EXIT_XSAVES:
12589 case VMX_EXIT_XRSTORS:
12590 case VMX_EXIT_UMWAIT:
12591 case VMX_EXIT_TPAUSE:
12592 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12593
12594 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12595 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12596 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12597 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12598 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12599 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12600 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12601 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12602 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12603 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12604 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12605 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12606 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12607 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12608 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12609 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12610 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12611 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12612 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12613
12614 case VMX_EXIT_PREEMPT_TIMER:
12615 {
12616 /** @todo NSTVMX: Preempt timer. */
12617 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12618 }
12619
12620 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12621 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12622
12623 case VMX_EXIT_VMREAD:
12624 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12625
12626 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12627 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12628
12629 case VMX_EXIT_INIT_SIGNAL:
12630 case VMX_EXIT_SIPI:
12631 case VMX_EXIT_IO_SMI:
12632 case VMX_EXIT_SMI:
12633 case VMX_EXIT_ERR_MSR_LOAD:
12634 case VMX_EXIT_ERR_MACHINE_CHECK:
12635 case VMX_EXIT_PML_FULL:
12636 case VMX_EXIT_RSM:
12637 default:
12638 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12639 }
12640}
12641#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12642
12643
12644/** @name VM-exit helpers.
12645 * @{
12646 */
12647/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12648/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12649/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12650
12651/** Macro for VM-exits called unexpectedly. */
12652#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12653 do { \
12654 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12655 return VERR_VMX_UNEXPECTED_EXIT; \
12656 } while (0)
12657
12658#ifdef VBOX_STRICT
12659/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12660# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12661 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12662
12663# define HMVMX_ASSERT_PREEMPT_CPUID() \
12664 do { \
12665 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12666 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12667 } while (0)
12668
12669# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12670 do { \
12671 AssertPtr((a_pVCpu)); \
12672 AssertPtr((a_pVmxTransient)); \
12673 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12674 Assert((a_pVmxTransient)->pVmcsInfo); \
12675 Assert(ASMIntAreEnabled()); \
12676 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12677 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12678 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12679 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12680 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12681 HMVMX_ASSERT_PREEMPT_CPUID(); \
12682 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12683 } while (0)
12684
12685# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12686 do { \
12687 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12688 Assert((a_pVmxTransient)->fIsNestedGuest); \
12689 } while (0)
12690
12691# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12692 do { \
12693 Log4Func(("\n")); \
12694 } while (0)
12695#else
12696# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12697 do { \
12698 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12699 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12700 } while (0)
12701
12702# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12703 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12704
12705# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12706#endif
12707
12708#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12709/** Macro that does the necessary privilege checks and intercepted VM-exits for
12710 * guests that attempted to execute a VMX instruction. */
12711# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12712 do \
12713 { \
12714 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12715 if (rcStrictTmp == VINF_SUCCESS) \
12716 { /* likely */ } \
12717 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12718 { \
12719 Assert((a_pVCpu)->hm.s.Event.fPending); \
12720 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12721 return VINF_SUCCESS; \
12722 } \
12723 else \
12724 { \
12725 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12726 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12727 } \
12728 } while (0)
12729
12730/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12731# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12732 do \
12733 { \
12734 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12735 (a_pGCPtrEffAddr)); \
12736 if (rcStrictTmp == VINF_SUCCESS) \
12737 { /* likely */ } \
12738 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12739 { \
12740 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12741 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12742 NOREF(uXcptTmp); \
12743 return VINF_SUCCESS; \
12744 } \
12745 else \
12746 { \
12747 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12748 return rcStrictTmp; \
12749 } \
12750 } while (0)
12751#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12752
12753
12754/**
12755 * Advances the guest RIP by the specified number of bytes.
12756 *
12757 * @param pVCpu The cross context virtual CPU structure.
12758 * @param cbInstr Number of bytes to advance the RIP by.
12759 *
12760 * @remarks No-long-jump zone!!!
12761 */
12762DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
12763{
12764 /* Advance the RIP. */
12765 pVCpu->cpum.GstCtx.rip += cbInstr;
12766 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12767
12768 /* Update interrupt inhibition. */
12769 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12770 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12771 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12772}
12773
12774
12775/**
12776 * Advances the guest RIP after reading it from the VMCS.
12777 *
12778 * @returns VBox status code, no informational status codes.
12779 * @param pVCpu The cross context virtual CPU structure.
12780 * @param pVmxTransient The VMX-transient structure.
12781 *
12782 * @remarks No-long-jump zone!!!
12783 */
12784static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12785{
12786 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12787 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12788 AssertRCReturn(rc, rc);
12789
12790 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
12791 return VINF_SUCCESS;
12792}
12793
12794
12795/**
12796 * Handle a condition that occurred while delivering an event through the guest or
12797 * nested-guest IDT.
12798 *
12799 * @returns Strict VBox status code (i.e. informational status codes too).
12800 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12801 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12802 * to continue execution of the guest which will delivery the \#DF.
12803 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12804 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12805 *
12806 * @param pVCpu The cross context virtual CPU structure.
12807 * @param pVmxTransient The VMX-transient structure.
12808 *
12809 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12810 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12811 * is due to an EPT violation, PML full or SPP-related event.
12812 *
12813 * @remarks No-long-jump zone!!!
12814 */
12815static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
12816{
12817 Assert(!pVCpu->hm.s.Event.fPending);
12818 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12819 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12820 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12821 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12822 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12823
12824 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12825 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12826 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12827 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12828 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12829 {
12830 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12831 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12832
12833 /*
12834 * If the event was a software interrupt (generated with INT n) or a software exception
12835 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12836 * can handle the VM-exit and continue guest execution which will re-execute the
12837 * instruction rather than re-injecting the exception, as that can cause premature
12838 * trips to ring-3 before injection and involve TRPM which currently has no way of
12839 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12840 * the problem).
12841 */
12842 IEMXCPTRAISE enmRaise;
12843 IEMXCPTRAISEINFO fRaiseInfo;
12844 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12845 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12846 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12847 {
12848 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12849 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12850 }
12851 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12852 {
12853 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12854 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12855 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12856
12857 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12858 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12859
12860 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12861
12862 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12863 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12864 {
12865 pVmxTransient->fVectoringPF = true;
12866 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12867 }
12868 }
12869 else
12870 {
12871 /*
12872 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12873 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12874 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12875 */
12876 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12877 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12878 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12879 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12880 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12881 }
12882
12883 /*
12884 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12885 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12886 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12887 * subsequent VM-entry would fail, see @bugref{7445}.
12888 *
12889 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12890 */
12891 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12892 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12893 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12894 && CPUMIsGuestNmiBlocking(pVCpu))
12895 {
12896 CPUMSetGuestNmiBlocking(pVCpu, false);
12897 }
12898
12899 switch (enmRaise)
12900 {
12901 case IEMXCPTRAISE_CURRENT_XCPT:
12902 {
12903 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
12904 Assert(rcStrict == VINF_SUCCESS);
12905 break;
12906 }
12907
12908 case IEMXCPTRAISE_PREV_EVENT:
12909 {
12910 uint32_t u32ErrCode;
12911 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
12912 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
12913 else
12914 u32ErrCode = 0;
12915
12916 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
12917 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
12918 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
12919 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
12920
12921 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
12922 pVCpu->hm.s.Event.u32ErrCode));
12923 Assert(rcStrict == VINF_SUCCESS);
12924 break;
12925 }
12926
12927 case IEMXCPTRAISE_REEXEC_INSTR:
12928 Assert(rcStrict == VINF_SUCCESS);
12929 break;
12930
12931 case IEMXCPTRAISE_DOUBLE_FAULT:
12932 {
12933 /*
12934 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
12935 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
12936 */
12937 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
12938 {
12939 pVmxTransient->fVectoringDoublePF = true;
12940 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
12941 pVCpu->cpum.GstCtx.cr2));
12942 rcStrict = VINF_SUCCESS;
12943 }
12944 else
12945 {
12946 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
12947 hmR0VmxSetPendingXcptDF(pVCpu);
12948 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
12949 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
12950 rcStrict = VINF_HM_DOUBLE_FAULT;
12951 }
12952 break;
12953 }
12954
12955 case IEMXCPTRAISE_TRIPLE_FAULT:
12956 {
12957 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
12958 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
12959 rcStrict = VINF_EM_RESET;
12960 break;
12961 }
12962
12963 case IEMXCPTRAISE_CPU_HANG:
12964 {
12965 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
12966 rcStrict = VERR_EM_GUEST_CPU_HANG;
12967 break;
12968 }
12969
12970 default:
12971 {
12972 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
12973 rcStrict = VERR_VMX_IPE_2;
12974 break;
12975 }
12976 }
12977 }
12978 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12979 && !CPUMIsGuestNmiBlocking(pVCpu))
12980 {
12981 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
12982 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
12983 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
12984 {
12985 /*
12986 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
12987 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
12988 * that NMIs remain blocked until the IRET execution is completed.
12989 *
12990 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
12991 */
12992 CPUMSetGuestNmiBlocking(pVCpu, true);
12993 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
12994 }
12995 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12996 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12997 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12998 {
12999 /*
13000 * Execution of IRET caused an EPT violation, page-modification log-full event or
13001 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13002 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13003 * that NMIs remain blocked until the IRET execution is completed.
13004 *
13005 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13006 */
13007 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13008 {
13009 CPUMSetGuestNmiBlocking(pVCpu, true);
13010 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13011 }
13012 }
13013 }
13014
13015 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13016 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13017 return rcStrict;
13018}
13019
13020
13021#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13022/**
13023 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13024 * guest attempting to execute a VMX instruction.
13025 *
13026 * @returns Strict VBox status code (i.e. informational status codes too).
13027 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13028 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13029 *
13030 * @param pVCpu The cross context virtual CPU structure.
13031 * @param uExitReason The VM-exit reason.
13032 *
13033 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13034 * @remarks No-long-jump zone!!!
13035 */
13036static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13037{
13038 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13039 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13040
13041 /*
13042 * The physical CPU would have already checked the CPU mode/code segment.
13043 * We shall just assert here for paranoia.
13044 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13045 */
13046 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13047 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13048 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13049
13050 if (uExitReason == VMX_EXIT_VMXON)
13051 {
13052 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13053
13054 /*
13055 * We check CR4.VMXE because it is required to be always set while in VMX operation
13056 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13057 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13058 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13059 */
13060 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13061 {
13062 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13063 hmR0VmxSetPendingXcptUD(pVCpu);
13064 return VINF_HM_PENDING_XCPT;
13065 }
13066 }
13067 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13068 {
13069 /*
13070 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13071 * (other than VMXON), we need to raise a #UD.
13072 */
13073 Log4Func(("Not in VMX root mode -> #UD\n"));
13074 hmR0VmxSetPendingXcptUD(pVCpu);
13075 return VINF_HM_PENDING_XCPT;
13076 }
13077
13078 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13079 return VINF_SUCCESS;
13080}
13081
13082
13083/**
13084 * Decodes the memory operand of an instruction that caused a VM-exit.
13085 *
13086 * The Exit qualification field provides the displacement field for memory
13087 * operand instructions, if any.
13088 *
13089 * @returns Strict VBox status code (i.e. informational status codes too).
13090 * @retval VINF_SUCCESS if the operand was successfully decoded.
13091 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13092 * operand.
13093 * @param pVCpu The cross context virtual CPU structure.
13094 * @param uExitInstrInfo The VM-exit instruction information field.
13095 * @param enmMemAccess The memory operand's access type (read or write).
13096 * @param GCPtrDisp The instruction displacement field, if any. For
13097 * RIP-relative addressing pass RIP + displacement here.
13098 * @param pGCPtrMem Where to store the effective destination memory address.
13099 *
13100 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13101 * virtual-8086 mode hence skips those checks while verifying if the
13102 * segment is valid.
13103 */
13104static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13105 PRTGCPTR pGCPtrMem)
13106{
13107 Assert(pGCPtrMem);
13108 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13109 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13110 | CPUMCTX_EXTRN_CR0);
13111
13112 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13113 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13114 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13115
13116 VMXEXITINSTRINFO ExitInstrInfo;
13117 ExitInstrInfo.u = uExitInstrInfo;
13118 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13119 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13120 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13121 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13122 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13123 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13124 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13125 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13126 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13127
13128 /*
13129 * Validate instruction information.
13130 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13131 */
13132 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13133 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13134 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13135 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13136 AssertLogRelMsgReturn(fIsMemOperand,
13137 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13138
13139 /*
13140 * Compute the complete effective address.
13141 *
13142 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13143 * See AMD spec. 4.5.2 "Segment Registers".
13144 */
13145 RTGCPTR GCPtrMem = GCPtrDisp;
13146 if (fBaseRegValid)
13147 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13148 if (fIdxRegValid)
13149 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13150
13151 RTGCPTR const GCPtrOff = GCPtrMem;
13152 if ( !fIsLongMode
13153 || iSegReg >= X86_SREG_FS)
13154 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13155 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13156
13157 /*
13158 * Validate effective address.
13159 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13160 */
13161 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13162 Assert(cbAccess > 0);
13163 if (fIsLongMode)
13164 {
13165 if (X86_IS_CANONICAL(GCPtrMem))
13166 {
13167 *pGCPtrMem = GCPtrMem;
13168 return VINF_SUCCESS;
13169 }
13170
13171 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13172 * "Data Limit Checks in 64-bit Mode". */
13173 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13174 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13175 return VINF_HM_PENDING_XCPT;
13176 }
13177
13178 /*
13179 * This is a watered down version of iemMemApplySegment().
13180 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13181 * and segment CPL/DPL checks are skipped.
13182 */
13183 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13184 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13185 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13186
13187 /* Check if the segment is present and usable. */
13188 if ( pSel->Attr.n.u1Present
13189 && !pSel->Attr.n.u1Unusable)
13190 {
13191 Assert(pSel->Attr.n.u1DescType);
13192 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13193 {
13194 /* Check permissions for the data segment. */
13195 if ( enmMemAccess == VMXMEMACCESS_WRITE
13196 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13197 {
13198 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13199 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13200 return VINF_HM_PENDING_XCPT;
13201 }
13202
13203 /* Check limits if it's a normal data segment. */
13204 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13205 {
13206 if ( GCPtrFirst32 > pSel->u32Limit
13207 || GCPtrLast32 > pSel->u32Limit)
13208 {
13209 Log4Func(("Data segment limit exceeded. "
13210 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13211 GCPtrLast32, pSel->u32Limit));
13212 if (iSegReg == X86_SREG_SS)
13213 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13214 else
13215 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13216 return VINF_HM_PENDING_XCPT;
13217 }
13218 }
13219 else
13220 {
13221 /* Check limits if it's an expand-down data segment.
13222 Note! The upper boundary is defined by the B bit, not the G bit! */
13223 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13224 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13225 {
13226 Log4Func(("Expand-down data segment limit exceeded. "
13227 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13228 GCPtrLast32, pSel->u32Limit));
13229 if (iSegReg == X86_SREG_SS)
13230 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13231 else
13232 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13233 return VINF_HM_PENDING_XCPT;
13234 }
13235 }
13236 }
13237 else
13238 {
13239 /* Check permissions for the code segment. */
13240 if ( enmMemAccess == VMXMEMACCESS_WRITE
13241 || ( enmMemAccess == VMXMEMACCESS_READ
13242 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13243 {
13244 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13245 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13246 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13247 return VINF_HM_PENDING_XCPT;
13248 }
13249
13250 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13251 if ( GCPtrFirst32 > pSel->u32Limit
13252 || GCPtrLast32 > pSel->u32Limit)
13253 {
13254 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13255 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13256 if (iSegReg == X86_SREG_SS)
13257 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13258 else
13259 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13260 return VINF_HM_PENDING_XCPT;
13261 }
13262 }
13263 }
13264 else
13265 {
13266 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13267 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13268 return VINF_HM_PENDING_XCPT;
13269 }
13270
13271 *pGCPtrMem = GCPtrMem;
13272 return VINF_SUCCESS;
13273}
13274#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13275
13276
13277/**
13278 * VM-exit helper for LMSW.
13279 */
13280static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13281{
13282 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13283 AssertRCReturn(rc, rc);
13284
13285 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13286 AssertMsg( rcStrict == VINF_SUCCESS
13287 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13288
13289 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13290 if (rcStrict == VINF_IEM_RAISED_XCPT)
13291 {
13292 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13293 rcStrict = VINF_SUCCESS;
13294 }
13295
13296 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13297 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13298 return rcStrict;
13299}
13300
13301
13302/**
13303 * VM-exit helper for CLTS.
13304 */
13305static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13306{
13307 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13308 AssertRCReturn(rc, rc);
13309
13310 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13311 AssertMsg( rcStrict == VINF_SUCCESS
13312 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13313
13314 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13315 if (rcStrict == VINF_IEM_RAISED_XCPT)
13316 {
13317 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13318 rcStrict = VINF_SUCCESS;
13319 }
13320
13321 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13322 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13323 return rcStrict;
13324}
13325
13326
13327/**
13328 * VM-exit helper for MOV from CRx (CRx read).
13329 */
13330static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13331{
13332 Assert(iCrReg < 16);
13333 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13334
13335 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13336 AssertRCReturn(rc, rc);
13337
13338 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13339 AssertMsg( rcStrict == VINF_SUCCESS
13340 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13341
13342 if (iGReg == X86_GREG_xSP)
13343 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13344 else
13345 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13346#ifdef VBOX_WITH_STATISTICS
13347 switch (iCrReg)
13348 {
13349 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13350 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13351 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13352 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13353 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13354 }
13355#endif
13356 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13357 return rcStrict;
13358}
13359
13360
13361/**
13362 * VM-exit helper for MOV to CRx (CRx write).
13363 */
13364static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13365{
13366 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13367 AssertRCReturn(rc, rc);
13368
13369 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13370 AssertMsg( rcStrict == VINF_SUCCESS
13371 || rcStrict == VINF_IEM_RAISED_XCPT
13372 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13373
13374 switch (iCrReg)
13375 {
13376 case 0:
13377 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13378 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13379 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13380 break;
13381
13382 case 2:
13383 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13384 /* Nothing to do here, CR2 it's not part of the VMCS. */
13385 break;
13386
13387 case 3:
13388 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13389 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13390 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13391 break;
13392
13393 case 4:
13394 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13395 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13396 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13397 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13398 break;
13399
13400 case 8:
13401 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13402 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13403 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13404 break;
13405
13406 default:
13407 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13408 break;
13409 }
13410
13411 if (rcStrict == VINF_IEM_RAISED_XCPT)
13412 {
13413 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13414 rcStrict = VINF_SUCCESS;
13415 }
13416 return rcStrict;
13417}
13418
13419
13420/**
13421 * VM-exit exception handler for \#PF (Page-fault exception).
13422 *
13423 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13424 */
13425static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13426{
13427 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13428 PVM pVM = pVCpu->CTX_SUFF(pVM);
13429 hmR0VmxReadExitQualVmcs(pVmxTransient);
13430
13431 if (!pVM->hm.s.fNestedPaging)
13432 { /* likely */ }
13433 else
13434 {
13435#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13436 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13437#endif
13438 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13439 if (!pVmxTransient->fVectoringDoublePF)
13440 {
13441 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13442 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13443 }
13444 else
13445 {
13446 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13447 Assert(!pVmxTransient->fIsNestedGuest);
13448 hmR0VmxSetPendingXcptDF(pVCpu);
13449 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13450 }
13451 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13452 return VINF_SUCCESS;
13453 }
13454
13455 Assert(!pVmxTransient->fIsNestedGuest);
13456
13457 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13458 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13459 if (pVmxTransient->fVectoringPF)
13460 {
13461 Assert(pVCpu->hm.s.Event.fPending);
13462 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13463 }
13464
13465 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13466 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13467 AssertRCReturn(rc, rc);
13468
13469 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
13470 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
13471
13472 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13473 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13474
13475 Log4Func(("#PF: rc=%Rrc\n", rc));
13476 if (rc == VINF_SUCCESS)
13477 {
13478 /*
13479 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13480 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13481 */
13482 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13483 TRPMResetTrap(pVCpu);
13484 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13485 return rc;
13486 }
13487
13488 if (rc == VINF_EM_RAW_GUEST_TRAP)
13489 {
13490 if (!pVmxTransient->fVectoringDoublePF)
13491 {
13492 /* It's a guest page fault and needs to be reflected to the guest. */
13493 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
13494 TRPMResetTrap(pVCpu);
13495 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13496 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13497 uGstErrorCode, pVmxTransient->uExitQual);
13498 }
13499 else
13500 {
13501 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13502 TRPMResetTrap(pVCpu);
13503 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13504 hmR0VmxSetPendingXcptDF(pVCpu);
13505 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13506 }
13507
13508 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13509 return VINF_SUCCESS;
13510 }
13511
13512 TRPMResetTrap(pVCpu);
13513 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13514 return rc;
13515}
13516
13517
13518/**
13519 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13520 *
13521 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13522 */
13523static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13524{
13525 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13526 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13527
13528 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13529 AssertRCReturn(rc, rc);
13530
13531 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13532 {
13533 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13534 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13535
13536 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13537 * provides VM-exit instruction length. If this causes problem later,
13538 * disassemble the instruction like it's done on AMD-V. */
13539 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13540 AssertRCReturn(rc2, rc2);
13541 return rc;
13542 }
13543
13544 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13545 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13546 return VINF_SUCCESS;
13547}
13548
13549
13550/**
13551 * VM-exit exception handler for \#BP (Breakpoint exception).
13552 *
13553 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13554 */
13555static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13556{
13557 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13558 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13559
13560 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13561 AssertRCReturn(rc, rc);
13562
13563 if (!pVmxTransient->fIsNestedGuest)
13564 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13565 else
13566 rc = VINF_EM_RAW_GUEST_TRAP;
13567 if (rc == VINF_EM_RAW_GUEST_TRAP)
13568 {
13569 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13570 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13571 rc = VINF_SUCCESS;
13572 }
13573
13574 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
13575 return rc;
13576}
13577
13578
13579/**
13580 * VM-exit exception handler for \#AC (Alignment-check exception).
13581 *
13582 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13583 */
13584static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13585{
13586 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13587 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13588
13589 /* Re-inject it. We'll detect any nesting before getting here. */
13590 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13591 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13592 return VINF_SUCCESS;
13593}
13594
13595
13596/**
13597 * VM-exit exception handler for \#DB (Debug exception).
13598 *
13599 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13600 */
13601static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13602{
13603 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13604 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13605
13606 /*
13607 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13608 */
13609 hmR0VmxReadExitQualVmcs(pVmxTransient);
13610
13611 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13612 uint64_t const uDR6 = X86_DR6_INIT_VAL
13613 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13614 | X86_DR6_BD | X86_DR6_BS));
13615
13616 int rc;
13617 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13618 if (!pVmxTransient->fIsNestedGuest)
13619 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13620 else
13621 rc = VINF_EM_RAW_GUEST_TRAP;
13622 Log6Func(("rc=%Rrc\n", rc));
13623 if (rc == VINF_EM_RAW_GUEST_TRAP)
13624 {
13625 /*
13626 * The exception was for the guest. Update DR6, DR7.GD and
13627 * IA32_DEBUGCTL.LBR before forwarding it.
13628 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13629 */
13630 VMMRZCallRing3Disable(pVCpu);
13631 HM_DISABLE_PREEMPT(pVCpu);
13632
13633 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13634 pCtx->dr[6] |= uDR6;
13635 if (CPUMIsGuestDebugStateActive(pVCpu))
13636 ASMSetDR6(pCtx->dr[6]);
13637
13638 HM_RESTORE_PREEMPT();
13639 VMMRZCallRing3Enable(pVCpu);
13640
13641 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13642 AssertRCReturn(rc, rc);
13643
13644 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13645 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13646
13647 /* Paranoia. */
13648 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13649 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13650
13651 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13652 AssertRC(rc);
13653
13654 /*
13655 * Raise #DB in the guest.
13656 *
13657 * It is important to reflect exactly what the VM-exit gave us (preserving the
13658 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13659 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13660 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13661 *
13662 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13663 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13664 */
13665 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13666 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13667 return VINF_SUCCESS;
13668 }
13669
13670 /*
13671 * Not a guest trap, must be a hypervisor related debug event then.
13672 * Update DR6 in case someone is interested in it.
13673 */
13674 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13675 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13676 CPUMSetHyperDR6(pVCpu, uDR6);
13677
13678 return rc;
13679}
13680
13681
13682/**
13683 * Hacks its way around the lovely mesa driver's backdoor accesses.
13684 *
13685 * @sa hmR0SvmHandleMesaDrvGp.
13686 */
13687static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13688{
13689 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13690 RT_NOREF(pCtx);
13691
13692 /* For now we'll just skip the instruction. */
13693 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13694}
13695
13696
13697/**
13698 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13699 * backdoor logging w/o checking what it is running inside.
13700 *
13701 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13702 * backdoor port and magic numbers loaded in registers.
13703 *
13704 * @returns true if it is, false if it isn't.
13705 * @sa hmR0SvmIsMesaDrvGp.
13706 */
13707DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13708{
13709 /* 0xed: IN eAX,dx */
13710 uint8_t abInstr[1];
13711 if (pVmxTransient->cbInstr != sizeof(abInstr))
13712 return false;
13713
13714 /* Check that it is #GP(0). */
13715 if (pVmxTransient->uExitIntErrorCode != 0)
13716 return false;
13717
13718 /* Check magic and port. */
13719 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13720 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13721 if (pCtx->rax != UINT32_C(0x564d5868))
13722 return false;
13723 if (pCtx->dx != UINT32_C(0x5658))
13724 return false;
13725
13726 /* Flat ring-3 CS. */
13727 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13728 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13729 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13730 if (pCtx->cs.Attr.n.u2Dpl != 3)
13731 return false;
13732 if (pCtx->cs.u64Base != 0)
13733 return false;
13734
13735 /* Check opcode. */
13736 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13737 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13738 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13739 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13740 if (RT_FAILURE(rc))
13741 return false;
13742 if (abInstr[0] != 0xed)
13743 return false;
13744
13745 return true;
13746}
13747
13748
13749/**
13750 * VM-exit exception handler for \#GP (General-protection exception).
13751 *
13752 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13753 */
13754static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13755{
13756 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13757 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13758
13759 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13760 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13761 if (pVmcsInfo->RealMode.fRealOnV86Active)
13762 { /* likely */ }
13763 else
13764 {
13765#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13766 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13767#endif
13768 /*
13769 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13770 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13771 */
13772 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13773 AssertRCReturn(rc, rc);
13774 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13775 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13776
13777 if ( pVmxTransient->fIsNestedGuest
13778 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13779 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13780 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13781 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13782 else
13783 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13784 return rc;
13785 }
13786
13787 Assert(CPUMIsGuestInRealModeEx(pCtx));
13788 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13789 Assert(!pVmxTransient->fIsNestedGuest);
13790
13791 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13792 AssertRCReturn(rc, rc);
13793
13794 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13795 if (rcStrict == VINF_SUCCESS)
13796 {
13797 if (!CPUMIsGuestInRealModeEx(pCtx))
13798 {
13799 /*
13800 * The guest is no longer in real-mode, check if we can continue executing the
13801 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13802 */
13803 pVmcsInfo->RealMode.fRealOnV86Active = false;
13804 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13805 {
13806 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13807 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13808 }
13809 else
13810 {
13811 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13812 rcStrict = VINF_EM_RESCHEDULE;
13813 }
13814 }
13815 else
13816 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13817 }
13818 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13819 {
13820 rcStrict = VINF_SUCCESS;
13821 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13822 }
13823 return VBOXSTRICTRC_VAL(rcStrict);
13824}
13825
13826
13827/**
13828 * VM-exit exception handler wrapper for all other exceptions that are not handled
13829 * by a specific handler.
13830 *
13831 * This simply re-injects the exception back into the VM without any special
13832 * processing.
13833 *
13834 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13835 */
13836static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13837{
13838 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13839
13840#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13841 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13842 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13843 ("uVector=%#x u32XcptBitmap=%#X32\n",
13844 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13845 NOREF(pVmcsInfo);
13846#endif
13847
13848 /*
13849 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13850 * would have been handled while checking exits due to event delivery.
13851 */
13852 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13853
13854#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13855 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13856 AssertRCReturn(rc, rc);
13857 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13858#endif
13859
13860#ifdef VBOX_WITH_STATISTICS
13861 switch (uVector)
13862 {
13863 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13864 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13865 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13866 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13867 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13868 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13869 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13870 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13871 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13872 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13873 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13874 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13875 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13876 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13877 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13878 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13879 default:
13880 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13881 break;
13882 }
13883#endif
13884
13885 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13886 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13887 NOREF(uVector);
13888
13889 /* Re-inject the original exception into the guest. */
13890 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
13891 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13892 return VINF_SUCCESS;
13893}
13894
13895
13896/**
13897 * VM-exit exception handler for all exceptions (except NMIs!).
13898 *
13899 * @remarks This may be called for both guests and nested-guests. Take care to not
13900 * make assumptions and avoid doing anything that is not relevant when
13901 * executing a nested-guest (e.g., Mesa driver hacks).
13902 */
13903static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13904{
13905 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13906
13907 /*
13908 * If this VM-exit occurred while delivering an event through the guest IDT, take
13909 * action based on the return code and additional hints (e.g. for page-faults)
13910 * that will be updated in the VMX transient structure.
13911 */
13912 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
13913 if (rcStrict == VINF_SUCCESS)
13914 {
13915 /*
13916 * If an exception caused a VM-exit due to delivery of an event, the original
13917 * event may have to be re-injected into the guest. We shall reinject it and
13918 * continue guest execution. However, page-fault is a complicated case and
13919 * needs additional processing done in hmR0VmxExitXcptPF().
13920 */
13921 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13922 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13923 if ( !pVCpu->hm.s.Event.fPending
13924 || uVector == X86_XCPT_PF)
13925 {
13926 switch (uVector)
13927 {
13928 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
13929 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
13930 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
13931 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
13932 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
13933 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
13934 default:
13935 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
13936 }
13937 }
13938 /* else: inject pending event before resuming guest execution. */
13939 }
13940 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
13941 {
13942 Assert(pVCpu->hm.s.Event.fPending);
13943 rcStrict = VINF_SUCCESS;
13944 }
13945
13946 return rcStrict;
13947}
13948/** @} */
13949
13950
13951/** @name VM-exit handlers.
13952 * @{
13953 */
13954/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13955/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13956/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13957
13958/**
13959 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
13960 */
13961HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13962{
13963 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13964 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
13965 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
13966 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
13967 return VINF_SUCCESS;
13968 return VINF_EM_RAW_INTERRUPT;
13969}
13970
13971
13972/**
13973 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
13974 * VM-exit.
13975 */
13976HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13977{
13978 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13979 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
13980
13981 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
13982
13983 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
13984 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13985 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13986
13987 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13988 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
13989 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
13990 NOREF(pVmcsInfo);
13991
13992 VBOXSTRICTRC rcStrict;
13993 switch (uExitIntType)
13994 {
13995 /*
13996 * Host physical NMIs:
13997 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
13998 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
13999 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14000 *
14001 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14002 * See Intel spec. 27.5.5 "Updating Non-Register State".
14003 */
14004 case VMX_EXIT_INT_INFO_TYPE_NMI:
14005 {
14006 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14007 break;
14008 }
14009
14010 /*
14011 * Privileged software exceptions (#DB from ICEBP),
14012 * Software exceptions (#BP and #OF),
14013 * Hardware exceptions:
14014 * Process the required exceptions and resume guest execution if possible.
14015 */
14016 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14017 Assert(uVector == X86_XCPT_DB);
14018 RT_FALL_THRU();
14019 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14020 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14021 RT_FALL_THRU();
14022 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14023 {
14024 NOREF(uVector);
14025 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14026 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14027 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14028 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14029
14030 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14031 break;
14032 }
14033
14034 default:
14035 {
14036 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14037 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14038 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14039 break;
14040 }
14041 }
14042
14043 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14044 return rcStrict;
14045}
14046
14047
14048/**
14049 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14050 */
14051HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14052{
14053 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14054
14055 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14056 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14057 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14058
14059 /* Evaluate and deliver pending events and resume guest execution. */
14060 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14061 return VINF_SUCCESS;
14062}
14063
14064
14065/**
14066 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14067 */
14068HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14069{
14070 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14071
14072 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14073 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14074 {
14075 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14076 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14077 }
14078
14079 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14080
14081 /*
14082 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14083 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14084 */
14085 uint32_t fIntrState;
14086 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14087 AssertRC(rc);
14088 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14089 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14090 {
14091 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14092 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14093
14094 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14095 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14096 AssertRC(rc);
14097 }
14098
14099 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14100 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14101
14102 /* Evaluate and deliver pending events and resume guest execution. */
14103 return VINF_SUCCESS;
14104}
14105
14106
14107/**
14108 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14109 */
14110HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14111{
14112 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14113 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14114}
14115
14116
14117/**
14118 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14119 */
14120HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14121{
14122 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14123 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14124}
14125
14126
14127/**
14128 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14129 */
14130HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14131{
14132 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14133
14134 /*
14135 * Get the state we need and update the exit history entry.
14136 */
14137 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14138 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14139
14140 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14141 AssertRCReturn(rc, rc);
14142
14143 VBOXSTRICTRC rcStrict;
14144 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14145 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14146 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14147 if (!pExitRec)
14148 {
14149 /*
14150 * Regular CPUID instruction execution.
14151 */
14152 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
14153 if (rcStrict == VINF_SUCCESS)
14154 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14155 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14156 {
14157 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14158 rcStrict = VINF_SUCCESS;
14159 }
14160 }
14161 else
14162 {
14163 /*
14164 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14165 */
14166 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14167 AssertRCReturn(rc2, rc2);
14168
14169 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14170 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14171
14172 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14173 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14174
14175 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14176 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14177 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14178 }
14179 return rcStrict;
14180}
14181
14182
14183/**
14184 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14185 */
14186HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14187{
14188 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14189
14190 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14191 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14192 AssertRCReturn(rc, rc);
14193
14194 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14195 return VINF_EM_RAW_EMULATE_INSTR;
14196
14197 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14198 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14199}
14200
14201
14202/**
14203 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14204 */
14205HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14206{
14207 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14208
14209 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14210 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14211 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14212 AssertRCReturn(rc, rc);
14213
14214 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
14215 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14216 {
14217 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14218 we must reset offsetting on VM-entry. See @bugref{6634}. */
14219 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14220 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14221 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14222 }
14223 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14224 {
14225 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14226 rcStrict = VINF_SUCCESS;
14227 }
14228 return rcStrict;
14229}
14230
14231
14232/**
14233 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14234 */
14235HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14236{
14237 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14238
14239 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14240 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14241 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14242 AssertRCReturn(rc, rc);
14243
14244 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
14245 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14246 {
14247 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14248 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14249 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14250 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14251 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14252 }
14253 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14254 {
14255 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14256 rcStrict = VINF_SUCCESS;
14257 }
14258 return rcStrict;
14259}
14260
14261
14262/**
14263 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14264 */
14265HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14266{
14267 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14268
14269 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14270 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14271 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14272 AssertRCReturn(rc, rc);
14273
14274 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14275 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14276 if (RT_LIKELY(rc == VINF_SUCCESS))
14277 {
14278 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14279 Assert(pVmxTransient->cbInstr == 2);
14280 }
14281 else
14282 {
14283 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14284 rc = VERR_EM_INTERPRETER;
14285 }
14286 return rc;
14287}
14288
14289
14290/**
14291 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14292 */
14293HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14294{
14295 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14296
14297 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14298 if (EMAreHypercallInstructionsEnabled(pVCpu))
14299 {
14300 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14301 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14302 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14303 AssertRCReturn(rc, rc);
14304
14305 /* Perform the hypercall. */
14306 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14307 if (rcStrict == VINF_SUCCESS)
14308 {
14309 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14310 AssertRCReturn(rc, rc);
14311 }
14312 else
14313 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14314 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14315 || RT_FAILURE(rcStrict));
14316
14317 /* If the hypercall changes anything other than guest's general-purpose registers,
14318 we would need to reload the guest changed bits here before VM-entry. */
14319 }
14320 else
14321 Log4Func(("Hypercalls not enabled\n"));
14322
14323 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14324 if (RT_FAILURE(rcStrict))
14325 {
14326 hmR0VmxSetPendingXcptUD(pVCpu);
14327 rcStrict = VINF_SUCCESS;
14328 }
14329
14330 return rcStrict;
14331}
14332
14333
14334/**
14335 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14336 */
14337HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14338{
14339 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14340 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14341
14342 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14343 hmR0VmxReadExitQualVmcs(pVmxTransient);
14344 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14345 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14346 AssertRCReturn(rc, rc);
14347
14348 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
14349
14350 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14351 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14352 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14353 {
14354 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14355 rcStrict = VINF_SUCCESS;
14356 }
14357 else
14358 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14359 VBOXSTRICTRC_VAL(rcStrict)));
14360 return rcStrict;
14361}
14362
14363
14364/**
14365 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14366 */
14367HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14368{
14369 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14370
14371 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14372 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14373 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14374 AssertRCReturn(rc, rc);
14375
14376 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
14377 if (rcStrict == VINF_SUCCESS)
14378 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14379 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14380 {
14381 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14382 rcStrict = VINF_SUCCESS;
14383 }
14384
14385 return rcStrict;
14386}
14387
14388
14389/**
14390 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14391 */
14392HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14393{
14394 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14395
14396 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14397 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14398 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14399 AssertRCReturn(rc, rc);
14400
14401 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
14402 if (RT_SUCCESS(rcStrict))
14403 {
14404 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14405 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14406 rcStrict = VINF_SUCCESS;
14407 }
14408
14409 return rcStrict;
14410}
14411
14412
14413/**
14414 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14415 * VM-exit.
14416 */
14417HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14418{
14419 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14420 return VINF_EM_RESET;
14421}
14422
14423
14424/**
14425 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14426 */
14427HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14428{
14429 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14430
14431 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14432 AssertRCReturn(rc, rc);
14433
14434 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14435 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14436 rc = VINF_SUCCESS;
14437 else
14438 rc = VINF_EM_HALT;
14439
14440 if (rc != VINF_SUCCESS)
14441 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14442 return rc;
14443}
14444
14445
14446/**
14447 * VM-exit handler for instructions that result in a \#UD exception delivered to
14448 * the guest.
14449 */
14450HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14451{
14452 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14453 hmR0VmxSetPendingXcptUD(pVCpu);
14454 return VINF_SUCCESS;
14455}
14456
14457
14458/**
14459 * VM-exit handler for expiry of the VMX-preemption timer.
14460 */
14461HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14462{
14463 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14464
14465 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14466 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14467
14468 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14469 PVM pVM = pVCpu->CTX_SUFF(pVM);
14470 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14471 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14472 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14473}
14474
14475
14476/**
14477 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14478 */
14479HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14480{
14481 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14482
14483 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14484 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14485 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14486 AssertRCReturn(rc, rc);
14487
14488 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
14489 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14490 : HM_CHANGED_RAISED_XCPT_MASK);
14491
14492 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14493 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14494
14495 return rcStrict;
14496}
14497
14498
14499/**
14500 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14501 */
14502HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14503{
14504 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14505 /** @todo Use VM-exit instruction information. */
14506 return VERR_EM_INTERPRETER;
14507}
14508
14509
14510/**
14511 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14512 * VM-exit.
14513 */
14514HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14515{
14516 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14517 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14518 AssertRCReturn(rc, rc);
14519
14520 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14521 if (RT_FAILURE(rc))
14522 return rc;
14523
14524 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14525 NOREF(uInvalidReason);
14526
14527#ifdef VBOX_STRICT
14528 uint32_t fIntrState;
14529 uint64_t u64Val;
14530 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14531 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14532 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14533
14534 Log4(("uInvalidReason %u\n", uInvalidReason));
14535 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14536 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14537 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14538
14539 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14540 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14541 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14542 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14543 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14544 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14545 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14546 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14547 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14548 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14549 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14550 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14551 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14552 {
14553 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14554 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14555 }
14556 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14557#endif
14558
14559 return VERR_VMX_INVALID_GUEST_STATE;
14560}
14561
14562/**
14563 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14564 */
14565HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14566{
14567 /*
14568 * Cummulative notes of all recognized but unexpected VM-exits.
14569 *
14570 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
14571 * nested-paging is used.
14572 *
14573 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14574 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14575 * this function (and thereby stop VM execution) for handling such instructions.
14576 *
14577 *
14578 * VMX_EXIT_INIT_SIGNAL:
14579 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14580 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14581 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14582 *
14583 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14584 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14585 * See Intel spec. "23.8 Restrictions on VMX operation".
14586 *
14587 * VMX_EXIT_SIPI:
14588 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14589 * activity state is used. We don't make use of it as our guests don't have direct
14590 * access to the host local APIC.
14591 *
14592 * See Intel spec. 25.3 "Other Causes of VM-exits".
14593 *
14594 * VMX_EXIT_IO_SMI:
14595 * VMX_EXIT_SMI:
14596 * This can only happen if we support dual-monitor treatment of SMI, which can be
14597 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14598 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14599 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14600 *
14601 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14602 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14603 *
14604 * VMX_EXIT_ERR_MSR_LOAD:
14605 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14606 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14607 * execution.
14608 *
14609 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14610 *
14611 * VMX_EXIT_ERR_MACHINE_CHECK:
14612 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14613 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14614 * #MC exception abort class exception is raised. We thus cannot assume a
14615 * reasonable chance of continuing any sort of execution and we bail.
14616 *
14617 * See Intel spec. 15.1 "Machine-check Architecture".
14618 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14619 *
14620 * VMX_EXIT_PML_FULL:
14621 * VMX_EXIT_VIRTUALIZED_EOI:
14622 * VMX_EXIT_APIC_WRITE:
14623 * We do not currently support any of these features and thus they are all unexpected
14624 * VM-exits.
14625 *
14626 * VMX_EXIT_GDTR_IDTR_ACCESS:
14627 * VMX_EXIT_LDTR_TR_ACCESS:
14628 * VMX_EXIT_RDRAND:
14629 * VMX_EXIT_RSM:
14630 * VMX_EXIT_VMFUNC:
14631 * VMX_EXIT_ENCLS:
14632 * VMX_EXIT_RDSEED:
14633 * VMX_EXIT_XSAVES:
14634 * VMX_EXIT_XRSTORS:
14635 * VMX_EXIT_UMWAIT:
14636 * VMX_EXIT_TPAUSE:
14637 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14638 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14639 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14640 *
14641 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14642 */
14643 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14644 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14645 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14646}
14647
14648
14649/**
14650 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14651 */
14652HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14653{
14654 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14655
14656 /** @todo Optimize this: We currently drag in in the whole MSR state
14657 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14658 * MSRs required. That would require changes to IEM and possibly CPUM too.
14659 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14660 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14661 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14662 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14663 switch (idMsr)
14664 {
14665 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14666 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14667 }
14668
14669 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14670 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14671 AssertRCReturn(rc, rc);
14672
14673 Log4Func(("ecx=%#RX32\n", idMsr));
14674
14675#ifdef VBOX_STRICT
14676 Assert(!pVmxTransient->fIsNestedGuest);
14677 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14678 {
14679 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14680 && idMsr != MSR_K6_EFER)
14681 {
14682 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14683 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14684 }
14685 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14686 {
14687 Assert(pVmcsInfo->pvMsrBitmap);
14688 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14689 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14690 {
14691 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14692 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14693 }
14694 }
14695 }
14696#endif
14697
14698 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
14699 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14700 if (rcStrict == VINF_SUCCESS)
14701 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14702 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
14703 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14704 {
14705 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14706 rcStrict = VINF_SUCCESS;
14707 }
14708 else
14709 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14710
14711 return rcStrict;
14712}
14713
14714
14715/**
14716 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14717 */
14718HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14719{
14720 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14721
14722 /** @todo Optimize this: We currently drag in in the whole MSR state
14723 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14724 * MSRs required. That would require changes to IEM and possibly CPUM too.
14725 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14726 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14727 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14728
14729 /*
14730 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14731 * Although we don't need to fetch the base as it will be overwritten shortly, while
14732 * loading guest-state we would also load the entire segment register including limit
14733 * and attributes and thus we need to load them here.
14734 */
14735 switch (idMsr)
14736 {
14737 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14738 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14739 }
14740
14741 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14742 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14743 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14744 AssertRCReturn(rc, rc);
14745
14746 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14747
14748 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
14749 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14750
14751 if (rcStrict == VINF_SUCCESS)
14752 {
14753 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14754
14755 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14756 if ( idMsr == MSR_IA32_APICBASE
14757 || ( idMsr >= MSR_IA32_X2APIC_START
14758 && idMsr <= MSR_IA32_X2APIC_END))
14759 {
14760 /*
14761 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14762 * When full APIC register virtualization is implemented we'll have to make
14763 * sure APIC state is saved from the VMCS before IEM changes it.
14764 */
14765 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14766 }
14767 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14768 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14769 else if (idMsr == MSR_K6_EFER)
14770 {
14771 /*
14772 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14773 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14774 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14775 */
14776 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14777 }
14778
14779 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14780 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14781 {
14782 switch (idMsr)
14783 {
14784 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14785 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14786 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14787 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14788 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14789 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14790 default:
14791 {
14792 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14793 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14794 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14795 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14796 break;
14797 }
14798 }
14799 }
14800#ifdef VBOX_STRICT
14801 else
14802 {
14803 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14804 switch (idMsr)
14805 {
14806 case MSR_IA32_SYSENTER_CS:
14807 case MSR_IA32_SYSENTER_EIP:
14808 case MSR_IA32_SYSENTER_ESP:
14809 case MSR_K8_FS_BASE:
14810 case MSR_K8_GS_BASE:
14811 {
14812 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14813 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14814 }
14815
14816 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14817 default:
14818 {
14819 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14820 {
14821 /* EFER MSR writes are always intercepted. */
14822 if (idMsr != MSR_K6_EFER)
14823 {
14824 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14825 idMsr));
14826 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14827 }
14828 }
14829
14830 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14831 {
14832 Assert(pVmcsInfo->pvMsrBitmap);
14833 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14834 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14835 {
14836 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14837 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14838 }
14839 }
14840 break;
14841 }
14842 }
14843 }
14844#endif /* VBOX_STRICT */
14845 }
14846 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14847 {
14848 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14849 rcStrict = VINF_SUCCESS;
14850 }
14851 else
14852 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14853
14854 return rcStrict;
14855}
14856
14857
14858/**
14859 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14860 */
14861HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14862{
14863 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14864
14865 /** @todo The guest has likely hit a contended spinlock. We might want to
14866 * poke a schedule different guest VCPU. */
14867 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14868 if (RT_SUCCESS(rc))
14869 return VINF_EM_RAW_INTERRUPT;
14870
14871 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
14872 return rc;
14873}
14874
14875
14876/**
14877 * VM-exit handler for when the TPR value is lowered below the specified
14878 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
14879 */
14880HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14881{
14882 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14883 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
14884
14885 /*
14886 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
14887 * We'll re-evaluate pending interrupts and inject them before the next VM
14888 * entry so we can just continue execution here.
14889 */
14890 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
14891 return VINF_SUCCESS;
14892}
14893
14894
14895/**
14896 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
14897 * VM-exit.
14898 *
14899 * @retval VINF_SUCCESS when guest execution can continue.
14900 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
14901 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
14902 * incompatible guest state for VMX execution (real-on-v86 case).
14903 */
14904HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14905{
14906 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14907 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
14908
14909 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14910 hmR0VmxReadExitQualVmcs(pVmxTransient);
14911 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14912
14913 VBOXSTRICTRC rcStrict;
14914 PVM pVM = pVCpu->CTX_SUFF(pVM);
14915 uint64_t const uExitQual = pVmxTransient->uExitQual;
14916 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
14917 switch (uAccessType)
14918 {
14919 /*
14920 * MOV to CRx.
14921 */
14922 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
14923 {
14924 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14925 AssertRCReturn(rc, rc);
14926
14927 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
14928 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
14929 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
14930 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
14931
14932 /*
14933 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
14934 * - When nested paging isn't used.
14935 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
14936 * - We are executing in the VM debug loop.
14937 */
14938 Assert( iCrReg != 3
14939 || !pVM->hm.s.fNestedPaging
14940 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
14941 || pVCpu->hm.s.fUsingDebugLoop);
14942
14943 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
14944 Assert( iCrReg != 8
14945 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
14946
14947 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
14948 AssertMsg( rcStrict == VINF_SUCCESS
14949 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14950
14951 /*
14952 * This is a kludge for handling switches back to real mode when we try to use
14953 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
14954 * deal with special selector values, so we have to return to ring-3 and run
14955 * there till the selector values are V86 mode compatible.
14956 *
14957 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
14958 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
14959 * this function.
14960 */
14961 if ( iCrReg == 0
14962 && rcStrict == VINF_SUCCESS
14963 && !pVM->hm.s.vmx.fUnrestrictedGuest
14964 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
14965 && (uOldCr0 & X86_CR0_PE)
14966 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
14967 {
14968 /** @todo Check selectors rather than returning all the time. */
14969 Assert(!pVmxTransient->fIsNestedGuest);
14970 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
14971 rcStrict = VINF_EM_RESCHEDULE_REM;
14972 }
14973 break;
14974 }
14975
14976 /*
14977 * MOV from CRx.
14978 */
14979 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
14980 {
14981 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
14982 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
14983
14984 /*
14985 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
14986 * - When nested paging isn't used.
14987 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
14988 * - We are executing in the VM debug loop.
14989 */
14990 Assert( iCrReg != 3
14991 || !pVM->hm.s.fNestedPaging
14992 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
14993 || pVCpu->hm.s.fUsingDebugLoop);
14994
14995 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
14996 Assert( iCrReg != 8
14997 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
14998
14999 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15000 break;
15001 }
15002
15003 /*
15004 * CLTS (Clear Task-Switch Flag in CR0).
15005 */
15006 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15007 {
15008 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15009 break;
15010 }
15011
15012 /*
15013 * LMSW (Load Machine-Status Word into CR0).
15014 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15015 */
15016 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15017 {
15018 RTGCPTR GCPtrEffDst;
15019 uint8_t const cbInstr = pVmxTransient->cbInstr;
15020 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15021 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15022 if (fMemOperand)
15023 {
15024 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15025 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15026 }
15027 else
15028 GCPtrEffDst = NIL_RTGCPTR;
15029 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15030 break;
15031 }
15032
15033 default:
15034 {
15035 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15036 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15037 }
15038 }
15039
15040 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15041 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15042 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15043
15044 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15045 NOREF(pVM);
15046 return rcStrict;
15047}
15048
15049
15050/**
15051 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15052 * VM-exit.
15053 */
15054HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15055{
15056 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15057 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15058
15059 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15060 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15061 hmR0VmxReadExitQualVmcs(pVmxTransient);
15062 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15063 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15064 | CPUMCTX_EXTRN_EFER);
15065 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15066 AssertRCReturn(rc, rc);
15067
15068 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15069 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15070 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15071 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15072 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15073 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15074 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15075 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15076
15077 /*
15078 * Update exit history to see if this exit can be optimized.
15079 */
15080 VBOXSTRICTRC rcStrict;
15081 PCEMEXITREC pExitRec = NULL;
15082 if ( !fGstStepping
15083 && !fDbgStepping)
15084 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15085 !fIOString
15086 ? !fIOWrite
15087 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15088 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15089 : !fIOWrite
15090 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15091 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15092 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15093 if (!pExitRec)
15094 {
15095 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15096 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15097
15098 uint32_t const cbValue = s_aIOSizes[uIOSize];
15099 uint32_t const cbInstr = pVmxTransient->cbInstr;
15100 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15101 PVM pVM = pVCpu->CTX_SUFF(pVM);
15102 if (fIOString)
15103 {
15104 /*
15105 * INS/OUTS - I/O String instruction.
15106 *
15107 * Use instruction-information if available, otherwise fall back on
15108 * interpreting the instruction.
15109 */
15110 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15111 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15112 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15113 if (fInsOutsInfo)
15114 {
15115 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15116 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15117 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15118 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15119 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15120 if (fIOWrite)
15121 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15122 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15123 else
15124 {
15125 /*
15126 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15127 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15128 * See Intel Instruction spec. for "INS".
15129 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15130 */
15131 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15132 }
15133 }
15134 else
15135 rcStrict = IEMExecOne(pVCpu);
15136
15137 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15138 fUpdateRipAlready = true;
15139 }
15140 else
15141 {
15142 /*
15143 * IN/OUT - I/O instruction.
15144 */
15145 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15146 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15147 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15148 if (fIOWrite)
15149 {
15150 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15151 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15152 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15153 && !pCtx->eflags.Bits.u1TF)
15154 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15155 }
15156 else
15157 {
15158 uint32_t u32Result = 0;
15159 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15160 if (IOM_SUCCESS(rcStrict))
15161 {
15162 /* Save result of I/O IN instr. in AL/AX/EAX. */
15163 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15164 }
15165 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15166 && !pCtx->eflags.Bits.u1TF)
15167 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15168 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15169 }
15170 }
15171
15172 if (IOM_SUCCESS(rcStrict))
15173 {
15174 if (!fUpdateRipAlready)
15175 {
15176 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15177 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15178 }
15179
15180 /*
15181 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15182 * while booting Fedora 17 64-bit guest.
15183 *
15184 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15185 */
15186 if (fIOString)
15187 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15188
15189 /*
15190 * If any I/O breakpoints are armed, we need to check if one triggered
15191 * and take appropriate action.
15192 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15193 */
15194 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15195 AssertRCReturn(rc, rc);
15196
15197 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15198 * execution engines about whether hyper BPs and such are pending. */
15199 uint32_t const uDr7 = pCtx->dr[7];
15200 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15201 && X86_DR7_ANY_RW_IO(uDr7)
15202 && (pCtx->cr4 & X86_CR4_DE))
15203 || DBGFBpIsHwIoArmed(pVM)))
15204 {
15205 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15206
15207 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15208 VMMRZCallRing3Disable(pVCpu);
15209 HM_DISABLE_PREEMPT(pVCpu);
15210
15211 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15212
15213 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15214 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15215 {
15216 /* Raise #DB. */
15217 if (fIsGuestDbgActive)
15218 ASMSetDR6(pCtx->dr[6]);
15219 if (pCtx->dr[7] != uDr7)
15220 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15221
15222 hmR0VmxSetPendingXcptDB(pVCpu);
15223 }
15224 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15225 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15226 else if ( rcStrict2 != VINF_SUCCESS
15227 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15228 rcStrict = rcStrict2;
15229 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15230
15231 HM_RESTORE_PREEMPT();
15232 VMMRZCallRing3Enable(pVCpu);
15233 }
15234 }
15235
15236#ifdef VBOX_STRICT
15237 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15238 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15239 Assert(!fIOWrite);
15240 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15241 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15242 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15243 Assert(fIOWrite);
15244 else
15245 {
15246# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15247 * statuses, that the VMM device and some others may return. See
15248 * IOM_SUCCESS() for guidance. */
15249 AssertMsg( RT_FAILURE(rcStrict)
15250 || rcStrict == VINF_SUCCESS
15251 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15252 || rcStrict == VINF_EM_DBG_BREAKPOINT
15253 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15254 || rcStrict == VINF_EM_RAW_TO_R3
15255 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15256# endif
15257 }
15258#endif
15259 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15260 }
15261 else
15262 {
15263 /*
15264 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15265 */
15266 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15267 AssertRCReturn(rc2, rc2);
15268 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15269 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15270 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15271 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15272 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15273 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15274
15275 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15276 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15277
15278 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15279 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15280 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15281 }
15282 return rcStrict;
15283}
15284
15285
15286/**
15287 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15288 * VM-exit.
15289 */
15290HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15291{
15292 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15293
15294 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15295 hmR0VmxReadExitQualVmcs(pVmxTransient);
15296 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15297 {
15298 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15299 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15300 {
15301 uint32_t uErrCode;
15302 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15303 {
15304 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15305 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15306 }
15307 else
15308 uErrCode = 0;
15309
15310 RTGCUINTPTR GCPtrFaultAddress;
15311 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15312 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15313 else
15314 GCPtrFaultAddress = 0;
15315
15316 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15317
15318 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15319 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
15320
15321 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15322 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15323 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15324 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15325 }
15326 }
15327
15328 /* Fall back to the interpreter to emulate the task-switch. */
15329 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15330 return VERR_EM_INTERPRETER;
15331}
15332
15333
15334/**
15335 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15336 */
15337HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15338{
15339 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15340
15341 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15342 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15343 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15344 AssertRC(rc);
15345 return VINF_EM_DBG_STEPPED;
15346}
15347
15348
15349/**
15350 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15351 */
15352HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15353{
15354 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15355 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15356
15357 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15358 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15359 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15360 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15361 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15362
15363 /*
15364 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15365 */
15366 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15367 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15368 {
15369 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15370 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15371 {
15372 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15373 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15374 }
15375 }
15376 else
15377 {
15378 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15379 return rcStrict;
15380 }
15381
15382 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15383 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15384 hmR0VmxReadExitQualVmcs(pVmxTransient);
15385 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15386 AssertRCReturn(rc, rc);
15387
15388 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15389 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15390 switch (uAccessType)
15391 {
15392 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15393 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15394 {
15395 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15396 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15397 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15398
15399 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15400 GCPhys &= PAGE_BASE_GC_MASK;
15401 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15402 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15403 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15404
15405 PVM pVM = pVCpu->CTX_SUFF(pVM);
15406 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15407 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
15408 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
15409 CPUMCTX2CORE(pCtx), GCPhys);
15410 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15411 if ( rcStrict == VINF_SUCCESS
15412 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15413 || rcStrict == VERR_PAGE_NOT_PRESENT)
15414 {
15415 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15416 | HM_CHANGED_GUEST_APIC_TPR);
15417 rcStrict = VINF_SUCCESS;
15418 }
15419 break;
15420 }
15421
15422 default:
15423 {
15424 Log4Func(("uAccessType=%#x\n", uAccessType));
15425 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15426 break;
15427 }
15428 }
15429
15430 if (rcStrict != VINF_SUCCESS)
15431 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15432 return rcStrict;
15433}
15434
15435
15436/**
15437 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15438 * VM-exit.
15439 */
15440HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15441{
15442 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15443 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15444
15445 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15446 if (!pVmxTransient->fIsNestedGuest)
15447 {
15448 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15449 if (pVmxTransient->fWasGuestDebugStateActive)
15450 {
15451 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15452 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15453 }
15454
15455 if ( !pVCpu->hm.s.fSingleInstruction
15456 && !pVmxTransient->fWasHyperDebugStateActive)
15457 {
15458 Assert(!DBGFIsStepping(pVCpu));
15459 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15460
15461 /* Don't intercept MOV DRx any more. */
15462 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15463 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15464 AssertRC(rc);
15465
15466 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15467 VMMRZCallRing3Disable(pVCpu);
15468 HM_DISABLE_PREEMPT(pVCpu);
15469
15470 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15471 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15472 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15473
15474 HM_RESTORE_PREEMPT();
15475 VMMRZCallRing3Enable(pVCpu);
15476
15477#ifdef VBOX_WITH_STATISTICS
15478 hmR0VmxReadExitQualVmcs(pVmxTransient);
15479 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15480 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15481 else
15482 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15483#endif
15484 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15485 return VINF_SUCCESS;
15486 }
15487 }
15488
15489 /*
15490 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15491 * The EFER MSR is always up-to-date.
15492 * Update the segment registers and DR7 from the CPU.
15493 */
15494 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15495 hmR0VmxReadExitQualVmcs(pVmxTransient);
15496 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15497 AssertRCReturn(rc, rc);
15498 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15499
15500 PVM pVM = pVCpu->CTX_SUFF(pVM);
15501 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15502 {
15503 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15504 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15505 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15506 if (RT_SUCCESS(rc))
15507 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15508 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15509 }
15510 else
15511 {
15512 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15513 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15514 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15515 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15516 }
15517
15518 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15519 if (RT_SUCCESS(rc))
15520 {
15521 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15522 AssertRCReturn(rc2, rc2);
15523 return VINF_SUCCESS;
15524 }
15525 return rc;
15526}
15527
15528
15529/**
15530 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15531 * Conditional VM-exit.
15532 */
15533HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15534{
15535 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15536 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15537
15538 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15539 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15540 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15541 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15542 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15543
15544 /*
15545 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15546 */
15547 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15548 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15549 {
15550 /*
15551 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15552 * instruction emulation to inject the original event. Otherwise, injecting the original event
15553 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
15554 */
15555 if (!pVCpu->hm.s.Event.fPending)
15556 { /* likely */ }
15557 else
15558 {
15559 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15560#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15561 /** @todo NSTVMX: Think about how this should be handled. */
15562 if (pVmxTransient->fIsNestedGuest)
15563 return VERR_VMX_IPE_3;
15564#endif
15565 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15566 }
15567 }
15568 else
15569 {
15570 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15571 return rcStrict;
15572 }
15573
15574 /*
15575 * Get sufficent state and update the exit history entry.
15576 */
15577 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15578 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15579 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15580 AssertRCReturn(rc, rc);
15581
15582 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15583 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15584 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15585 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15586 if (!pExitRec)
15587 {
15588 /*
15589 * If we succeed, resume guest execution.
15590 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15591 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15592 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15593 * weird case. See @bugref{6043}.
15594 */
15595 PVM pVM = pVCpu->CTX_SUFF(pVM);
15596 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15597 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15598 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15599 if ( rcStrict == VINF_SUCCESS
15600 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15601 || rcStrict == VERR_PAGE_NOT_PRESENT)
15602 {
15603 /* Successfully handled MMIO operation. */
15604 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15605 | HM_CHANGED_GUEST_APIC_TPR);
15606 rcStrict = VINF_SUCCESS;
15607 }
15608 }
15609 else
15610 {
15611 /*
15612 * Frequent exit or something needing probing. Call EMHistoryExec.
15613 */
15614 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15615 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15616
15617 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15618 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15619
15620 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15621 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15622 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15623 }
15624 return rcStrict;
15625}
15626
15627
15628/**
15629 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15630 * VM-exit.
15631 */
15632HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15633{
15634 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15635 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15636
15637 hmR0VmxReadExitQualVmcs(pVmxTransient);
15638 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15639 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15640 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15641 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15642 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15643
15644 /*
15645 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15646 */
15647 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15648 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15649 {
15650 /*
15651 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15652 * we shall resolve the nested #PF and re-inject the original event.
15653 */
15654 if (pVCpu->hm.s.Event.fPending)
15655 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15656 }
15657 else
15658 {
15659 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15660 return rcStrict;
15661 }
15662
15663 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15664 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15665 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15666 AssertRCReturn(rc, rc);
15667
15668 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15669 uint64_t const uExitQual = pVmxTransient->uExitQual;
15670 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15671
15672 RTGCUINT uErrorCode = 0;
15673 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15674 uErrorCode |= X86_TRAP_PF_ID;
15675 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15676 uErrorCode |= X86_TRAP_PF_RW;
15677 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15678 uErrorCode |= X86_TRAP_PF_P;
15679
15680 PVM pVM = pVCpu->CTX_SUFF(pVM);
15681 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15682 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15683
15684 /*
15685 * Handle the pagefault trap for the nested shadow table.
15686 */
15687 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15688 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15689 TRPMResetTrap(pVCpu);
15690
15691 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15692 if ( rcStrict == VINF_SUCCESS
15693 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15694 || rcStrict == VERR_PAGE_NOT_PRESENT)
15695 {
15696 /* Successfully synced our nested page tables. */
15697 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15698 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15699 return VINF_SUCCESS;
15700 }
15701
15702 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15703 return rcStrict;
15704}
15705
15706
15707#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15708/**
15709 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15710 */
15711HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15712{
15713 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15714
15715 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15716 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15717 hmR0VmxReadExitQualVmcs(pVmxTransient);
15718 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15719 | CPUMCTX_EXTRN_HWVIRT
15720 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15721 AssertRCReturn(rc, rc);
15722
15723 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15724
15725 VMXVEXITINFO ExitInfo;
15726 RT_ZERO(ExitInfo);
15727 ExitInfo.uReason = pVmxTransient->uExitReason;
15728 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15729 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15730 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15731 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15732
15733 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15734 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15735 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15736 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15737 {
15738 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15739 rcStrict = VINF_SUCCESS;
15740 }
15741 return rcStrict;
15742}
15743
15744
15745/**
15746 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15747 */
15748HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15749{
15750 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15751
15752 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15753 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15754 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15755 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15756 AssertRCReturn(rc, rc);
15757
15758 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15759
15760 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15761 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
15762 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15763 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15764 {
15765 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15766 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15767 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15768 }
15769 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15770 return rcStrict;
15771}
15772
15773
15774/**
15775 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15776 */
15777HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15778{
15779 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15780
15781 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15782 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15783 hmR0VmxReadExitQualVmcs(pVmxTransient);
15784 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15785 | CPUMCTX_EXTRN_HWVIRT
15786 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15787 AssertRCReturn(rc, rc);
15788
15789 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15790
15791 VMXVEXITINFO ExitInfo;
15792 RT_ZERO(ExitInfo);
15793 ExitInfo.uReason = pVmxTransient->uExitReason;
15794 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15795 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15796 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15797 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15798
15799 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15800 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15801 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15802 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15803 {
15804 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15805 rcStrict = VINF_SUCCESS;
15806 }
15807 return rcStrict;
15808}
15809
15810
15811/**
15812 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15813 */
15814HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15815{
15816 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15817
15818 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15819 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15820 hmR0VmxReadExitQualVmcs(pVmxTransient);
15821 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15822 | CPUMCTX_EXTRN_HWVIRT
15823 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15824 AssertRCReturn(rc, rc);
15825
15826 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15827
15828 VMXVEXITINFO ExitInfo;
15829 RT_ZERO(ExitInfo);
15830 ExitInfo.uReason = pVmxTransient->uExitReason;
15831 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15832 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15833 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15834 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15835
15836 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15837 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15838 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15839 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15840 {
15841 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15842 rcStrict = VINF_SUCCESS;
15843 }
15844 return rcStrict;
15845}
15846
15847
15848/**
15849 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15850 */
15851HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15852{
15853 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15854
15855 /*
15856 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15857 * thus might not need to import the shadow VMCS state, it's safer just in case
15858 * code elsewhere dares look at unsynced VMCS fields.
15859 */
15860 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15861 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15862 hmR0VmxReadExitQualVmcs(pVmxTransient);
15863 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15864 | CPUMCTX_EXTRN_HWVIRT
15865 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15866 AssertRCReturn(rc, rc);
15867
15868 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15869
15870 VMXVEXITINFO ExitInfo;
15871 RT_ZERO(ExitInfo);
15872 ExitInfo.uReason = pVmxTransient->uExitReason;
15873 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15874 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15875 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15876 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15877 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15878
15879 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
15880 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15881 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15882 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15883 {
15884 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15885 rcStrict = VINF_SUCCESS;
15886 }
15887 return rcStrict;
15888}
15889
15890
15891/**
15892 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
15893 */
15894HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15895{
15896 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15897
15898 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
15899 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15900 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15901 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15902 AssertRCReturn(rc, rc);
15903
15904 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15905
15906 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15907 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
15908 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15909 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15910 {
15911 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15912 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15913 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15914 }
15915 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15916 return rcStrict;
15917}
15918
15919
15920/**
15921 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
15922 */
15923HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15924{
15925 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15926
15927 /*
15928 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
15929 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
15930 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
15931 */
15932 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15933 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15934 hmR0VmxReadExitQualVmcs(pVmxTransient);
15935 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15936 | CPUMCTX_EXTRN_HWVIRT
15937 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15938 AssertRCReturn(rc, rc);
15939
15940 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15941
15942 VMXVEXITINFO ExitInfo;
15943 RT_ZERO(ExitInfo);
15944 ExitInfo.uReason = pVmxTransient->uExitReason;
15945 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15946 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15947 ExitInfo.cbInstr = pVmxTransient->cbInstr;
15948 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15949 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15950
15951 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
15952 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15953 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15954 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15955 {
15956 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15957 rcStrict = VINF_SUCCESS;
15958 }
15959 return rcStrict;
15960}
15961
15962
15963/**
15964 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
15965 */
15966HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15967{
15968 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15969
15970 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15971 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
15972 | CPUMCTX_EXTRN_HWVIRT
15973 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15974 AssertRCReturn(rc, rc);
15975
15976 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15977
15978 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
15979 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15980 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
15981 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15982 {
15983 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15984 rcStrict = VINF_SUCCESS;
15985 }
15986 return rcStrict;
15987}
15988
15989
15990/**
15991 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
15992 */
15993HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15994{
15995 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15996
15997 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15998 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15999 hmR0VmxReadExitQualVmcs(pVmxTransient);
16000 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16001 | CPUMCTX_EXTRN_HWVIRT
16002 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16003 AssertRCReturn(rc, rc);
16004
16005 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16006
16007 VMXVEXITINFO ExitInfo;
16008 RT_ZERO(ExitInfo);
16009 ExitInfo.uReason = pVmxTransient->uExitReason;
16010 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16011 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16012 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16013 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16014
16015 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16016 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16017 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16018 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16019 {
16020 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16021 rcStrict = VINF_SUCCESS;
16022 }
16023 return rcStrict;
16024}
16025
16026
16027/**
16028 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16029 */
16030HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16031{
16032 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16033
16034 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16035 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16036 hmR0VmxReadExitQualVmcs(pVmxTransient);
16037 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16038 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16039 AssertRCReturn(rc, rc);
16040
16041 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16042
16043 VMXVEXITINFO ExitInfo;
16044 RT_ZERO(ExitInfo);
16045 ExitInfo.uReason = pVmxTransient->uExitReason;
16046 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16047 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16048 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16049 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16050
16051 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16052 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16053 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16054 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16055 {
16056 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16057 rcStrict = VINF_SUCCESS;
16058 }
16059 return rcStrict;
16060}
16061#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16062/** @} */
16063
16064
16065#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16066/** @name Nested-guest VM-exit handlers.
16067 * @{
16068 */
16069/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16070/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16071/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16072
16073/**
16074 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16075 * Conditional VM-exit.
16076 */
16077HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16078{
16079 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16080
16081 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16082
16083 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16084 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16085 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16086
16087 switch (uExitIntType)
16088 {
16089 /*
16090 * Physical NMIs:
16091 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16092 */
16093 case VMX_EXIT_INT_INFO_TYPE_NMI:
16094 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16095
16096 /*
16097 * Hardware exceptions,
16098 * Software exceptions,
16099 * Privileged software exceptions:
16100 * Figure out if the exception must be delivered to the guest or the nested-guest.
16101 */
16102 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16103 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16104 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16105 {
16106 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16107 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16108 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16109 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16110
16111 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16112 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16113 pVmxTransient->uExitIntErrorCode);
16114 if (fIntercept)
16115 {
16116 /* Exit qualification is required for debug and page-fault exceptions. */
16117 hmR0VmxReadExitQualVmcs(pVmxTransient);
16118
16119 /*
16120 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16121 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16122 * length. However, if delivery of a software interrupt, software exception or privileged
16123 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16124 */
16125 VMXVEXITINFO ExitInfo;
16126 RT_ZERO(ExitInfo);
16127 ExitInfo.uReason = pVmxTransient->uExitReason;
16128 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16129 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16130
16131 VMXVEXITEVENTINFO ExitEventInfo;
16132 RT_ZERO(ExitEventInfo);
16133 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16134 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16135 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16136 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16137
16138#ifdef DEBUG_ramshankar
16139 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16140 Log4Func(("exit_int_info=%#x err_code=%#x exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16141 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16142 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16143 {
16144 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16145 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16146 }
16147
16148 /* DOS VM debugging (IRET). */
16149 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_GPRS);
16150 uint8_t abStack[64];
16151 int rc = PGMPhysSimpleReadGCPtr(pVCpu, &abStack[0], pCtx->esp, sizeof(abStack));
16152 if (RT_SUCCESS(rc))
16153 Log(("StackMem: %.*Rhxs\n", sizeof(abStack), abStack));
16154#endif
16155 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16156 }
16157
16158 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16159 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16160 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16161 }
16162
16163 /*
16164 * Software interrupts:
16165 * VM-exits cannot be caused by software interrupts.
16166 *
16167 * External interrupts:
16168 * This should only happen when "acknowledge external interrupts on VM-exit"
16169 * control is set. However, we never set this when executing a guest or
16170 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16171 * the guest.
16172 */
16173 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16174 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16175 default:
16176 {
16177 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16178 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16179 }
16180 }
16181}
16182
16183
16184/**
16185 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16186 * Unconditional VM-exit.
16187 */
16188HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16189{
16190 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16191 return IEMExecVmxVmexitTripleFault(pVCpu);
16192}
16193
16194
16195/**
16196 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16197 */
16198HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16199{
16200 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16201
16202 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16203 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16204 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16205}
16206
16207
16208/**
16209 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16210 */
16211HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16212{
16213 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16214
16215 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16216 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16217 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16218}
16219
16220
16221/**
16222 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16223 * Unconditional VM-exit.
16224 */
16225HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16226{
16227 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16228
16229 hmR0VmxReadExitQualVmcs(pVmxTransient);
16230 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16231 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16232 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16233
16234 VMXVEXITINFO ExitInfo;
16235 RT_ZERO(ExitInfo);
16236 ExitInfo.uReason = pVmxTransient->uExitReason;
16237 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16238 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16239
16240 VMXVEXITEVENTINFO ExitEventInfo;
16241 RT_ZERO(ExitEventInfo);
16242 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16243 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16244 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16245}
16246
16247
16248/**
16249 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16250 */
16251HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16252{
16253 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16254
16255 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16256 {
16257 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16258 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16259 }
16260 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16261}
16262
16263
16264/**
16265 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16266 */
16267HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16268{
16269 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16270
16271 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16272 {
16273 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16274 hmR0VmxReadExitQualVmcs(pVmxTransient);
16275
16276 VMXVEXITINFO ExitInfo;
16277 RT_ZERO(ExitInfo);
16278 ExitInfo.uReason = pVmxTransient->uExitReason;
16279 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16280 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16281 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16282 }
16283 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16284}
16285
16286
16287/**
16288 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16289 */
16290HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16291{
16292 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16293
16294 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16295 {
16296 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16297 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16298 }
16299 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16300}
16301
16302
16303/**
16304 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16305 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16306 */
16307HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16308{
16309 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16310
16311 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16312 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16313
16314 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16315
16316 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16317 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16318 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16319
16320 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16321 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16322 u64VmcsField &= UINT64_C(0xffffffff);
16323
16324 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16325 {
16326 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16327 hmR0VmxReadExitQualVmcs(pVmxTransient);
16328
16329 VMXVEXITINFO ExitInfo;
16330 RT_ZERO(ExitInfo);
16331 ExitInfo.uReason = pVmxTransient->uExitReason;
16332 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16333 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16334 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16335 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16336 }
16337
16338 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16339 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16340 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16341}
16342
16343
16344/**
16345 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16346 */
16347HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16348{
16349 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16350
16351 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16352 {
16353 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16354 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16355 }
16356
16357 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16358}
16359
16360
16361/**
16362 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16363 * Conditional VM-exit.
16364 */
16365HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16366{
16367 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16368
16369 hmR0VmxReadExitQualVmcs(pVmxTransient);
16370 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16371
16372 VBOXSTRICTRC rcStrict;
16373 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16374 switch (uAccessType)
16375 {
16376 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16377 {
16378 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16379 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16380 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16381 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16382
16383 bool fIntercept;
16384 switch (iCrReg)
16385 {
16386 case 0:
16387 case 4:
16388 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16389 break;
16390
16391 case 3:
16392 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16393 break;
16394
16395 case 8:
16396 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16397 break;
16398
16399 default:
16400 fIntercept = false;
16401 break;
16402 }
16403 if (fIntercept)
16404 {
16405 VMXVEXITINFO ExitInfo;
16406 RT_ZERO(ExitInfo);
16407 ExitInfo.uReason = pVmxTransient->uExitReason;
16408 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16409 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16410 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16411 }
16412 else
16413 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
16414 break;
16415 }
16416
16417 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16418 {
16419 /*
16420 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16421 * CR2 reads do not cause a VM-exit.
16422 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16423 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16424 */
16425 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16426 if ( iCrReg == 3
16427 || iCrReg == 8)
16428 {
16429 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16430 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16431 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16432 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
16433 {
16434 VMXVEXITINFO ExitInfo;
16435 RT_ZERO(ExitInfo);
16436 ExitInfo.uReason = pVmxTransient->uExitReason;
16437 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16438 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16439 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16440 }
16441 else
16442 {
16443 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16444 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
16445 }
16446 }
16447 else
16448 {
16449 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16450 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16451 }
16452 break;
16453 }
16454
16455 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16456 {
16457 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16458 Assert(pVmcsNstGst);
16459 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16460 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16461 if ( (uGstHostMask & X86_CR0_TS)
16462 && (uReadShadow & X86_CR0_TS))
16463 {
16464 VMXVEXITINFO ExitInfo;
16465 RT_ZERO(ExitInfo);
16466 ExitInfo.uReason = pVmxTransient->uExitReason;
16467 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16468 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16469 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16470 }
16471 else
16472 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
16473 break;
16474 }
16475
16476 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16477 {
16478 RTGCPTR GCPtrEffDst;
16479 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16480 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16481 if (fMemOperand)
16482 {
16483 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16484 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16485 }
16486 else
16487 GCPtrEffDst = NIL_RTGCPTR;
16488
16489 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
16490 {
16491 VMXVEXITINFO ExitInfo;
16492 RT_ZERO(ExitInfo);
16493 ExitInfo.uReason = pVmxTransient->uExitReason;
16494 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16495 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16496 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16497 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16498 }
16499 else
16500 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
16501 break;
16502 }
16503
16504 default:
16505 {
16506 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16507 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16508 }
16509 }
16510
16511 if (rcStrict == VINF_IEM_RAISED_XCPT)
16512 {
16513 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16514 rcStrict = VINF_SUCCESS;
16515 }
16516 return rcStrict;
16517}
16518
16519
16520/**
16521 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16522 * Conditional VM-exit.
16523 */
16524HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16525{
16526 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16527
16528 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16529 {
16530 hmR0VmxReadExitQualVmcs(pVmxTransient);
16531 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16532
16533 VMXVEXITINFO ExitInfo;
16534 RT_ZERO(ExitInfo);
16535 ExitInfo.uReason = pVmxTransient->uExitReason;
16536 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16537 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16538 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16539 }
16540 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16541}
16542
16543
16544/**
16545 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16546 * Conditional VM-exit.
16547 */
16548HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16549{
16550 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16551
16552 hmR0VmxReadExitQualVmcs(pVmxTransient);
16553
16554 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16555 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16556 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16557
16558 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16559 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16560 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16561 {
16562 /*
16563 * IN/OUT instruction:
16564 * - Provides VM-exit instruction length.
16565 *
16566 * INS/OUTS instruction:
16567 * - Provides VM-exit instruction length.
16568 * - Provides Guest-linear address.
16569 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16570 */
16571 PVM pVM = pVCpu->CTX_SUFF(pVM);
16572 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16573
16574 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16575 pVmxTransient->ExitInstrInfo.u = 0;
16576 pVmxTransient->uGuestLinearAddr = 0;
16577
16578 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16579 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16580 if (fIOString)
16581 {
16582 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16583 if (fVmxInsOutsInfo)
16584 {
16585 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16586 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16587 }
16588 }
16589
16590 VMXVEXITINFO ExitInfo;
16591 RT_ZERO(ExitInfo);
16592 ExitInfo.uReason = pVmxTransient->uExitReason;
16593 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16594 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16595 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16596 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16597 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16598 }
16599 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16600}
16601
16602
16603/**
16604 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16605 */
16606HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16607{
16608 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16609
16610 uint32_t fMsrpm;
16611 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16612 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16613 else
16614 fMsrpm = VMXMSRPM_EXIT_RD;
16615
16616 if (fMsrpm & VMXMSRPM_EXIT_RD)
16617 {
16618 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16619 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16620 }
16621 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16622}
16623
16624
16625/**
16626 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16627 */
16628HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16629{
16630 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16631
16632 uint32_t fMsrpm;
16633 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16634 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16635 else
16636 fMsrpm = VMXMSRPM_EXIT_WR;
16637
16638 if (fMsrpm & VMXMSRPM_EXIT_WR)
16639 {
16640 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16641 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16642 }
16643 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16644}
16645
16646
16647/**
16648 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16649 */
16650HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16651{
16652 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16653
16654 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16655 {
16656 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16657 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16658 }
16659 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16660}
16661
16662
16663/**
16664 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16665 * VM-exit.
16666 */
16667HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16668{
16669 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16670
16671 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16672 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16673}
16674
16675
16676/**
16677 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16678 */
16679HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16680{
16681 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16682
16683 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16684 {
16685 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16686 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16687 }
16688 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16689}
16690
16691
16692/**
16693 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16694 */
16695HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16696{
16697 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16698
16699 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16700 * PAUSE when executing a nested-guest? If it does not, we would not need
16701 * to check for the intercepts here. Just call VM-exit... */
16702
16703 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16704 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16705 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16706 {
16707 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16708 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16709 }
16710 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16711}
16712
16713
16714/**
16715 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16716 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16717 */
16718HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16719{
16720 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16721
16722 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16723 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16724 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16725}
16726
16727
16728/**
16729 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16730 * VM-exit.
16731 */
16732HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16733{
16734 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16735
16736 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16737 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16738 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16739 hmR0VmxReadExitQualVmcs(pVmxTransient);
16740
16741 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16742
16743 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16744 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16745
16746 VMXVEXITINFO ExitInfo;
16747 RT_ZERO(ExitInfo);
16748 ExitInfo.uReason = pVmxTransient->uExitReason;
16749 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16750 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16751
16752 VMXVEXITEVENTINFO ExitEventInfo;
16753 RT_ZERO(ExitEventInfo);
16754 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16755 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16756 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16757}
16758
16759
16760/**
16761 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16762 * Conditional VM-exit.
16763 */
16764HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16765{
16766 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16767
16768 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16769 hmR0VmxReadExitQualVmcs(pVmxTransient);
16770 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16771}
16772
16773
16774/**
16775 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16776 * Conditional VM-exit.
16777 */
16778HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16779{
16780 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16781
16782 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16783 hmR0VmxReadExitQualVmcs(pVmxTransient);
16784 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16785}
16786
16787
16788/**
16789 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16790 */
16791HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16792{
16793 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16794
16795 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16796 {
16797 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16798 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16799 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16800 }
16801 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16802}
16803
16804
16805/**
16806 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16807 */
16808HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16809{
16810 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16811
16812 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16813 {
16814 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16815 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16816 }
16817 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16818}
16819
16820
16821/**
16822 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16823 */
16824HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16825{
16826 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16827
16828 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16829 {
16830 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16831 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16832 hmR0VmxReadExitQualVmcs(pVmxTransient);
16833 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16834
16835 VMXVEXITINFO ExitInfo;
16836 RT_ZERO(ExitInfo);
16837 ExitInfo.uReason = pVmxTransient->uExitReason;
16838 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16839 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16840 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16841 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16842 }
16843 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16844}
16845
16846
16847/**
16848 * Nested-guest VM-exit handler for invalid-guest state
16849 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16850 */
16851HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16852{
16853 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16854
16855 /*
16856 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16857 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16858 * Handle it like it's in an invalid guest state of the outer guest.
16859 *
16860 * When the fast path is implemented, this should be changed to cause the corresponding
16861 * nested-guest VM-exit.
16862 */
16863 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
16864}
16865
16866
16867/**
16868 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
16869 * and only provide the instruction length.
16870 *
16871 * Unconditional VM-exit.
16872 */
16873HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16874{
16875 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16876
16877#ifdef VBOX_STRICT
16878 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16879 switch (pVmxTransient->uExitReason)
16880 {
16881 case VMX_EXIT_ENCLS:
16882 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
16883 break;
16884
16885 case VMX_EXIT_VMFUNC:
16886 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
16887 break;
16888 }
16889#endif
16890
16891 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16892 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
16893}
16894
16895
16896/**
16897 * Nested-guest VM-exit handler for instructions that provide instruction length as
16898 * well as more information.
16899 *
16900 * Unconditional VM-exit.
16901 */
16902HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16903{
16904 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16905
16906#ifdef VBOX_STRICT
16907 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16908 switch (pVmxTransient->uExitReason)
16909 {
16910 case VMX_EXIT_GDTR_IDTR_ACCESS:
16911 case VMX_EXIT_LDTR_TR_ACCESS:
16912 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
16913 break;
16914
16915 case VMX_EXIT_RDRAND:
16916 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
16917 break;
16918
16919 case VMX_EXIT_RDSEED:
16920 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
16921 break;
16922
16923 case VMX_EXIT_XSAVES:
16924 case VMX_EXIT_XRSTORS:
16925 /** @todo NSTVMX: Verify XSS-bitmap. */
16926 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
16927 break;
16928
16929 case VMX_EXIT_UMWAIT:
16930 case VMX_EXIT_TPAUSE:
16931 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
16932 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
16933 break;
16934 }
16935#endif
16936
16937 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16938 hmR0VmxReadExitQualVmcs(pVmxTransient);
16939 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16940
16941 VMXVEXITINFO ExitInfo;
16942 RT_ZERO(ExitInfo);
16943 ExitInfo.uReason = pVmxTransient->uExitReason;
16944 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16945 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16946 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16947 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16948}
16949
16950/** @} */
16951#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16952
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