VirtualBox

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

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

VMM: fCtxChanged isn't volatile.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 707.9 KB
Line 
1/* $Id: HMVMXR0.cpp 81277 2019-10-15 05:11:00Z 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#include "HMInternal.h"
39#include <VBox/vmm/vmcc.h>
40#include <VBox/vmm/hmvmxinline.h>
41#include "HMVMXR0.h"
42#include "dtrace/VBoxVMM.h"
43
44#ifdef DEBUG_ramshankar
45# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
46# define HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
47# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
48# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
49# define HMVMX_ALWAYS_CLEAN_TRANSIENT
50# define HMVMX_ALWAYS_CHECK_GUEST_STATE
51# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
52# define HMVMX_ALWAYS_TRAP_PF
53# define HMVMX_ALWAYS_FLUSH_TLB
54# define HMVMX_ALWAYS_SWAP_EFER
55#endif
56
57
58/*********************************************************************************************************************************
59* Defined Constants And Macros *
60*********************************************************************************************************************************/
61/** Use the function table. */
62#define HMVMX_USE_FUNCTION_TABLE
63
64/** Determine which tagged-TLB flush handler to use. */
65#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
66#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
67#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
68#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
69
70/**
71 * Flags to skip redundant reads of some common VMCS fields that are not part of
72 * the guest-CPU or VCPU state but are needed while handling VM-exits.
73 */
74#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
75#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
76#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
77#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
78#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
79#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
80#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
81#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
82#define HMVMX_READ_GUEST_PHYSICAL_ADDR RT_BIT_32(8)
83#define HMVMX_READ_GUEST_PENDING_DBG_XCPTS RT_BIT_32(9)
84
85/** All the VMCS fields required for processing of exception/NMI VM-exits. */
86#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
87 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
88 | HMVMX_READ_EXIT_INSTR_LEN \
89 | HMVMX_READ_IDT_VECTORING_INFO \
90 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
91
92/** Assert that all the given fields have been read from the VMCS. */
93#ifdef VBOX_STRICT
94# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) \
95 do { \
96 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead); \
97 Assert((fVmcsFieldRead & (a_fReadFields)) == (a_fReadFields)); \
98 } while (0)
99#else
100# define HMVMX_ASSERT_READ(a_pVmxTransient, a_fReadFields) do { } while (0)
101#endif
102
103/**
104 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
105 * guest using hardware-assisted VMX.
106 *
107 * This excludes state like GPRs (other than RSP) which are always are
108 * swapped and restored across the world-switch and also registers like EFER,
109 * MSR which cannot be modified by the guest without causing a VM-exit.
110 */
111#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
112 | CPUMCTX_EXTRN_RFLAGS \
113 | CPUMCTX_EXTRN_RSP \
114 | CPUMCTX_EXTRN_SREG_MASK \
115 | CPUMCTX_EXTRN_TABLE_MASK \
116 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
117 | CPUMCTX_EXTRN_SYSCALL_MSRS \
118 | CPUMCTX_EXTRN_SYSENTER_MSRS \
119 | CPUMCTX_EXTRN_TSC_AUX \
120 | CPUMCTX_EXTRN_OTHER_MSRS \
121 | CPUMCTX_EXTRN_CR0 \
122 | CPUMCTX_EXTRN_CR3 \
123 | CPUMCTX_EXTRN_CR4 \
124 | CPUMCTX_EXTRN_DR7 \
125 | CPUMCTX_EXTRN_HWVIRT \
126 | CPUMCTX_EXTRN_HM_VMX_MASK)
127
128/**
129 * Exception bitmap mask for real-mode guests (real-on-v86).
130 *
131 * We need to intercept all exceptions manually except:
132 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
133 * due to bugs in Intel CPUs.
134 * - \#PF need not be intercepted even in real-mode if we have nested paging
135 * support.
136 */
137#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
138 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
139 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
140 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
141 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
142 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
143 | RT_BIT(X86_XCPT_XF))
144
145/** Maximum VM-instruction error number. */
146#define HMVMX_INSTR_ERROR_MAX 28
147
148/** Profiling macro. */
149#ifdef HM_PROFILE_EXIT_DISPATCH
150# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
151# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
152#else
153# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
154# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
155#endif
156
157/** Assert that preemption is disabled or covered by thread-context hooks. */
158#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
159 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
160
161/** Assert that we haven't migrated CPUs when thread-context hooks are not
162 * used. */
163#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
164 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
165 ("Illegal migration! Entered on CPU %u Current %u\n", \
166 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
167
168/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
169 * context. */
170#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
171 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
172 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
173
174/** Log the VM-exit reason with an easily visible marker to identify it in a
175 * potential sea of logging data. */
176#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
177 do { \
178 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, \
179 HMGetVmxExitName(a_uExitReason))); \
180 } while (0) \
181
182
183/*********************************************************************************************************************************
184* Structures and Typedefs *
185*********************************************************************************************************************************/
186/**
187 * VMX per-VCPU transient state.
188 *
189 * A state structure for holding miscellaneous information across
190 * VMX non-root operation and restored after the transition.
191 */
192typedef struct VMXTRANSIENT
193{
194 /** The host's rflags/eflags. */
195 RTCCUINTREG fEFlags;
196
197 /** The guest's TPR value used for TPR shadowing. */
198 uint8_t u8GuestTpr;
199 /** Alignment. */
200 uint8_t abAlignment0[7];
201
202 /** The basic VM-exit reason. */
203 uint16_t uExitReason;
204 /** Alignment. */
205 uint16_t u16Alignment0;
206 /** The VM-exit interruption error code. */
207 uint32_t uExitIntErrorCode;
208 /** The VM-exit exit code qualification. */
209 uint64_t uExitQual;
210 /** The Guest-linear address. */
211 uint64_t uGuestLinearAddr;
212 /** The Guest-physical address. */
213 uint64_t uGuestPhysicalAddr;
214 /** The Guest pending-debug exceptions. */
215 uint64_t uGuestPendingDbgXcpts;
216
217 /** The VM-exit interruption-information field. */
218 uint32_t uExitIntInfo;
219 /** The VM-exit instruction-length field. */
220 uint32_t cbExitInstr;
221 /** The VM-exit instruction-information field. */
222 VMXEXITINSTRINFO ExitInstrInfo;
223 /** Whether the VM-entry failed or not. */
224 bool fVMEntryFailed;
225 /** Whether we are currently executing a nested-guest. */
226 bool fIsNestedGuest;
227 /** Alignment. */
228 uint8_t abAlignment1[2];
229
230 /** The VM-entry interruption-information field. */
231 uint32_t uEntryIntInfo;
232 /** The VM-entry exception error code field. */
233 uint32_t uEntryXcptErrorCode;
234 /** The VM-entry instruction length field. */
235 uint32_t cbEntryInstr;
236
237 /** IDT-vectoring information field. */
238 uint32_t uIdtVectoringInfo;
239 /** IDT-vectoring error code. */
240 uint32_t uIdtVectoringErrorCode;
241
242 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
243 uint32_t fVmcsFieldsRead;
244
245 /** Whether the guest debug state was active at the time of VM-exit. */
246 bool fWasGuestDebugStateActive;
247 /** Whether the hyper debug state was active at the time of VM-exit. */
248 bool fWasHyperDebugStateActive;
249 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
250 bool fUpdatedTscOffsettingAndPreemptTimer;
251 /** Whether the VM-exit was caused by a page-fault during delivery of a
252 * contributory exception or a page-fault. */
253 bool fVectoringDoublePF;
254 /** Whether the VM-exit was caused by a page-fault during delivery of an
255 * external interrupt or NMI. */
256 bool fVectoringPF;
257 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
258 * area after VM-exit. */
259 bool fRemoveTscAuxMsr;
260 bool afAlignment0[2];
261
262 /** The VMCS info. object. */
263 PVMXVMCSINFO pVmcsInfo;
264} VMXTRANSIENT;
265AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
266AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
267AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
268AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
269AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
270AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
271/** Pointer to VMX transient state. */
272typedef VMXTRANSIENT *PVMXTRANSIENT;
273/** Pointer to a const VMX transient state. */
274typedef const VMXTRANSIENT *PCVMXTRANSIENT;
275
276/**
277 * Memory operand read or write access.
278 */
279typedef enum VMXMEMACCESS
280{
281 VMXMEMACCESS_READ = 0,
282 VMXMEMACCESS_WRITE = 1
283} VMXMEMACCESS;
284
285/**
286 * VMX VM-exit handler.
287 *
288 * @returns Strict VBox status code (i.e. informational status codes too).
289 * @param pVCpu The cross context virtual CPU structure.
290 * @param pVmxTransient The VMX-transient structure.
291 */
292#ifndef HMVMX_USE_FUNCTION_TABLE
293typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
294#else
295typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
296/** Pointer to VM-exit handler. */
297typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
298#endif
299
300/**
301 * VMX VM-exit handler, non-strict status code.
302 *
303 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
304 *
305 * @returns VBox status code, no informational status code returned.
306 * @param pVCpu The cross context virtual CPU structure.
307 * @param pVmxTransient The VMX-transient structure.
308 *
309 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
310 * use of that status code will be replaced with VINF_EM_SOMETHING
311 * later when switching over to IEM.
312 */
313#ifndef HMVMX_USE_FUNCTION_TABLE
314typedef int FNVMXEXITHANDLERNSRC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
315#else
316typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
317#endif
318
319
320/*********************************************************************************************************************************
321* Internal Functions *
322*********************************************************************************************************************************/
323#ifndef HMVMX_USE_FUNCTION_TABLE
324DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
325# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
326# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
327#else
328# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
329# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
330#endif
331#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
332DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient);
333#endif
334
335static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
336
337/** @name VM-exit handler prototypes.
338 * @{
339 */
340static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
341static FNVMXEXITHANDLER hmR0VmxExitExtInt;
342static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
343static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
344static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
345static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
346static FNVMXEXITHANDLER hmR0VmxExitCpuid;
347static FNVMXEXITHANDLER hmR0VmxExitGetsec;
348static FNVMXEXITHANDLER hmR0VmxExitHlt;
349static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
350static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
351static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
352static FNVMXEXITHANDLER hmR0VmxExitVmcall;
353#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
354static FNVMXEXITHANDLER hmR0VmxExitVmclear;
355static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
356static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
357static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
358static FNVMXEXITHANDLER hmR0VmxExitVmread;
359static FNVMXEXITHANDLER hmR0VmxExitVmresume;
360static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
361static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
362static FNVMXEXITHANDLER hmR0VmxExitVmxon;
363static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
364#endif
365static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
366static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
367static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
368static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
369static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
370static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
371static FNVMXEXITHANDLER hmR0VmxExitMwait;
372static FNVMXEXITHANDLER hmR0VmxExitMtf;
373static FNVMXEXITHANDLER hmR0VmxExitMonitor;
374static FNVMXEXITHANDLER hmR0VmxExitPause;
375static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
376static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
377static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
378static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
379static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
380static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
381static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
382static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
383static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
384static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
385static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
386static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
387/** @} */
388
389#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
390/** @name Nested-guest VM-exit handler prototypes.
391 * @{
392 */
393static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
394static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
395static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
396static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
397static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
398static FNVMXEXITHANDLER hmR0VmxExitHltNested;
399static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
400static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
401static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
402static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
403static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
404static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
405static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
406static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
407static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
408static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
409static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
410static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
411static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
412static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
413static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
414static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
415static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
416static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
417static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
418static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
419static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
420static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
421static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
422/** @} */
423#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
424
425
426/*********************************************************************************************************************************
427* Global Variables *
428*********************************************************************************************************************************/
429#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
430/**
431 * Array of all VMCS fields.
432 * Any fields added to the VT-x spec. should be added here.
433 *
434 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
435 * of nested-guests.
436 */
437static const uint32_t g_aVmcsFields[] =
438{
439 /* 16-bit control fields. */
440 VMX_VMCS16_VPID,
441 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
442 VMX_VMCS16_EPTP_INDEX,
443
444 /* 16-bit guest-state fields. */
445 VMX_VMCS16_GUEST_ES_SEL,
446 VMX_VMCS16_GUEST_CS_SEL,
447 VMX_VMCS16_GUEST_SS_SEL,
448 VMX_VMCS16_GUEST_DS_SEL,
449 VMX_VMCS16_GUEST_FS_SEL,
450 VMX_VMCS16_GUEST_GS_SEL,
451 VMX_VMCS16_GUEST_LDTR_SEL,
452 VMX_VMCS16_GUEST_TR_SEL,
453 VMX_VMCS16_GUEST_INTR_STATUS,
454 VMX_VMCS16_GUEST_PML_INDEX,
455
456 /* 16-bits host-state fields. */
457 VMX_VMCS16_HOST_ES_SEL,
458 VMX_VMCS16_HOST_CS_SEL,
459 VMX_VMCS16_HOST_SS_SEL,
460 VMX_VMCS16_HOST_DS_SEL,
461 VMX_VMCS16_HOST_FS_SEL,
462 VMX_VMCS16_HOST_GS_SEL,
463 VMX_VMCS16_HOST_TR_SEL,
464
465 /* 64-bit control fields. */
466 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
467 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
468 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
469 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
470 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
471 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
472 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
473 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
474 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
475 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
476 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
477 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
478 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
479 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
480 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
481 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
482 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
483 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
484 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
485 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
486 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
487 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
488 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
489 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
490 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
491 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
492 VMX_VMCS64_CTRL_EPTP_FULL,
493 VMX_VMCS64_CTRL_EPTP_HIGH,
494 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
495 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
496 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
497 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
498 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
499 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
500 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
501 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
502 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
503 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
504 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
505 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
506 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
507 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
508 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
509 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
510 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
511 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
512 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
513 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
514 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
515 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
516
517 /* 64-bit read-only data fields. */
518 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
519 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
520
521 /* 64-bit guest-state fields. */
522 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
523 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
524 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
525 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
526 VMX_VMCS64_GUEST_PAT_FULL,
527 VMX_VMCS64_GUEST_PAT_HIGH,
528 VMX_VMCS64_GUEST_EFER_FULL,
529 VMX_VMCS64_GUEST_EFER_HIGH,
530 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
531 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
532 VMX_VMCS64_GUEST_PDPTE0_FULL,
533 VMX_VMCS64_GUEST_PDPTE0_HIGH,
534 VMX_VMCS64_GUEST_PDPTE1_FULL,
535 VMX_VMCS64_GUEST_PDPTE1_HIGH,
536 VMX_VMCS64_GUEST_PDPTE2_FULL,
537 VMX_VMCS64_GUEST_PDPTE2_HIGH,
538 VMX_VMCS64_GUEST_PDPTE3_FULL,
539 VMX_VMCS64_GUEST_PDPTE3_HIGH,
540 VMX_VMCS64_GUEST_BNDCFGS_FULL,
541 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
542
543 /* 64-bit host-state fields. */
544 VMX_VMCS64_HOST_PAT_FULL,
545 VMX_VMCS64_HOST_PAT_HIGH,
546 VMX_VMCS64_HOST_EFER_FULL,
547 VMX_VMCS64_HOST_EFER_HIGH,
548 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
549 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
550
551 /* 32-bit control fields. */
552 VMX_VMCS32_CTRL_PIN_EXEC,
553 VMX_VMCS32_CTRL_PROC_EXEC,
554 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
555 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
556 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
557 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
558 VMX_VMCS32_CTRL_EXIT,
559 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
560 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
561 VMX_VMCS32_CTRL_ENTRY,
562 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
563 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
564 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
565 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
566 VMX_VMCS32_CTRL_TPR_THRESHOLD,
567 VMX_VMCS32_CTRL_PROC_EXEC2,
568 VMX_VMCS32_CTRL_PLE_GAP,
569 VMX_VMCS32_CTRL_PLE_WINDOW,
570
571 /* 32-bits read-only fields. */
572 VMX_VMCS32_RO_VM_INSTR_ERROR,
573 VMX_VMCS32_RO_EXIT_REASON,
574 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
575 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
576 VMX_VMCS32_RO_IDT_VECTORING_INFO,
577 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
578 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
579 VMX_VMCS32_RO_EXIT_INSTR_INFO,
580
581 /* 32-bit guest-state fields. */
582 VMX_VMCS32_GUEST_ES_LIMIT,
583 VMX_VMCS32_GUEST_CS_LIMIT,
584 VMX_VMCS32_GUEST_SS_LIMIT,
585 VMX_VMCS32_GUEST_DS_LIMIT,
586 VMX_VMCS32_GUEST_FS_LIMIT,
587 VMX_VMCS32_GUEST_GS_LIMIT,
588 VMX_VMCS32_GUEST_LDTR_LIMIT,
589 VMX_VMCS32_GUEST_TR_LIMIT,
590 VMX_VMCS32_GUEST_GDTR_LIMIT,
591 VMX_VMCS32_GUEST_IDTR_LIMIT,
592 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
593 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
594 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
595 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
596 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
597 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
598 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
599 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
600 VMX_VMCS32_GUEST_INT_STATE,
601 VMX_VMCS32_GUEST_ACTIVITY_STATE,
602 VMX_VMCS32_GUEST_SMBASE,
603 VMX_VMCS32_GUEST_SYSENTER_CS,
604 VMX_VMCS32_PREEMPT_TIMER_VALUE,
605
606 /* 32-bit host-state fields. */
607 VMX_VMCS32_HOST_SYSENTER_CS,
608
609 /* Natural-width control fields. */
610 VMX_VMCS_CTRL_CR0_MASK,
611 VMX_VMCS_CTRL_CR4_MASK,
612 VMX_VMCS_CTRL_CR0_READ_SHADOW,
613 VMX_VMCS_CTRL_CR4_READ_SHADOW,
614 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
615 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
616 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
617 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
618
619 /* Natural-width read-only data fields. */
620 VMX_VMCS_RO_EXIT_QUALIFICATION,
621 VMX_VMCS_RO_IO_RCX,
622 VMX_VMCS_RO_IO_RSI,
623 VMX_VMCS_RO_IO_RDI,
624 VMX_VMCS_RO_IO_RIP,
625 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
626
627 /* Natural-width guest-state field */
628 VMX_VMCS_GUEST_CR0,
629 VMX_VMCS_GUEST_CR3,
630 VMX_VMCS_GUEST_CR4,
631 VMX_VMCS_GUEST_ES_BASE,
632 VMX_VMCS_GUEST_CS_BASE,
633 VMX_VMCS_GUEST_SS_BASE,
634 VMX_VMCS_GUEST_DS_BASE,
635 VMX_VMCS_GUEST_FS_BASE,
636 VMX_VMCS_GUEST_GS_BASE,
637 VMX_VMCS_GUEST_LDTR_BASE,
638 VMX_VMCS_GUEST_TR_BASE,
639 VMX_VMCS_GUEST_GDTR_BASE,
640 VMX_VMCS_GUEST_IDTR_BASE,
641 VMX_VMCS_GUEST_DR7,
642 VMX_VMCS_GUEST_RSP,
643 VMX_VMCS_GUEST_RIP,
644 VMX_VMCS_GUEST_RFLAGS,
645 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
646 VMX_VMCS_GUEST_SYSENTER_ESP,
647 VMX_VMCS_GUEST_SYSENTER_EIP,
648
649 /* Natural-width host-state fields */
650 VMX_VMCS_HOST_CR0,
651 VMX_VMCS_HOST_CR3,
652 VMX_VMCS_HOST_CR4,
653 VMX_VMCS_HOST_FS_BASE,
654 VMX_VMCS_HOST_GS_BASE,
655 VMX_VMCS_HOST_TR_BASE,
656 VMX_VMCS_HOST_GDTR_BASE,
657 VMX_VMCS_HOST_IDTR_BASE,
658 VMX_VMCS_HOST_SYSENTER_ESP,
659 VMX_VMCS_HOST_SYSENTER_EIP,
660 VMX_VMCS_HOST_RSP,
661 VMX_VMCS_HOST_RIP
662};
663#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
664
665static const uint32_t g_aVmcsSegBase[] =
666{
667 VMX_VMCS_GUEST_ES_BASE,
668 VMX_VMCS_GUEST_CS_BASE,
669 VMX_VMCS_GUEST_SS_BASE,
670 VMX_VMCS_GUEST_DS_BASE,
671 VMX_VMCS_GUEST_FS_BASE,
672 VMX_VMCS_GUEST_GS_BASE
673};
674static const uint32_t g_aVmcsSegSel[] =
675{
676 VMX_VMCS16_GUEST_ES_SEL,
677 VMX_VMCS16_GUEST_CS_SEL,
678 VMX_VMCS16_GUEST_SS_SEL,
679 VMX_VMCS16_GUEST_DS_SEL,
680 VMX_VMCS16_GUEST_FS_SEL,
681 VMX_VMCS16_GUEST_GS_SEL
682};
683static const uint32_t g_aVmcsSegLimit[] =
684{
685 VMX_VMCS32_GUEST_ES_LIMIT,
686 VMX_VMCS32_GUEST_CS_LIMIT,
687 VMX_VMCS32_GUEST_SS_LIMIT,
688 VMX_VMCS32_GUEST_DS_LIMIT,
689 VMX_VMCS32_GUEST_FS_LIMIT,
690 VMX_VMCS32_GUEST_GS_LIMIT
691};
692static const uint32_t g_aVmcsSegAttr[] =
693{
694 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
695 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
696 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
697 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
698 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
699 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
700};
701AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
702AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
703AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
704AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
705
706#ifdef HMVMX_USE_FUNCTION_TABLE
707/**
708 * VMX_EXIT dispatch table.
709 */
710static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
711{
712 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
713 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
714 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
715 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
716 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
717 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
718 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
719 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
720 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
721 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
722 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
723 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
724 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
725 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
726 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
727 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
728 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
729 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
730 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
731#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
732 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
733 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
734 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
735 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
736 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
737 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
738 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
739 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
740 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
741#else
742 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
743 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
744 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
745 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
746 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
747 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
748 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
749 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
750 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
751#endif
752 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
753 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
754 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
755 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
756 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
757 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
758 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
759 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
760 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
761 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
762 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
763 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
764 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
765 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
766 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
767 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
768 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
769 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
770 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
771 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
772 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
773 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
774 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
775 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
776 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
777#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
778 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
779#else
780 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
781#endif
782 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
783 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
784 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
785 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
786 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
787 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
788 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
789 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
790 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
791 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
792 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
793 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
794 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
795 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
796 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
797};
798#endif /* HMVMX_USE_FUNCTION_TABLE */
799
800#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
801static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
802{
803 /* 0 */ "(Not Used)",
804 /* 1 */ "VMCALL executed in VMX root operation.",
805 /* 2 */ "VMCLEAR with invalid physical address.",
806 /* 3 */ "VMCLEAR with VMXON pointer.",
807 /* 4 */ "VMLAUNCH with non-clear VMCS.",
808 /* 5 */ "VMRESUME with non-launched VMCS.",
809 /* 6 */ "VMRESUME after VMXOFF",
810 /* 7 */ "VM-entry with invalid control fields.",
811 /* 8 */ "VM-entry with invalid host state fields.",
812 /* 9 */ "VMPTRLD with invalid physical address.",
813 /* 10 */ "VMPTRLD with VMXON pointer.",
814 /* 11 */ "VMPTRLD with incorrect revision identifier.",
815 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
816 /* 13 */ "VMWRITE to read-only VMCS component.",
817 /* 14 */ "(Not Used)",
818 /* 15 */ "VMXON executed in VMX root operation.",
819 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
820 /* 17 */ "VM-entry with non-launched executing VMCS.",
821 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
822 /* 19 */ "VMCALL with non-clear VMCS.",
823 /* 20 */ "VMCALL with invalid VM-exit control fields.",
824 /* 21 */ "(Not Used)",
825 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
826 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
827 /* 24 */ "VMCALL with invalid SMM-monitor features.",
828 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
829 /* 26 */ "VM-entry with events blocked by MOV SS.",
830 /* 27 */ "(Not Used)",
831 /* 28 */ "Invalid operand to INVEPT/INVVPID."
832};
833#endif /* VBOX_STRICT && LOG_ENABLED */
834
835
836/**
837 * Gets the CR0 guest/host mask.
838 *
839 * These bits typically does not change through the lifetime of a VM. Any bit set in
840 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
841 * by the guest.
842 *
843 * @returns The CR0 guest/host mask.
844 * @param pVCpu The cross context virtual CPU structure.
845 */
846static uint64_t hmR0VmxGetFixedCr0Mask(PCVMCPUCC 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 * Furthermore, modifications to any bits that are reserved/unspecified currently
853 * by the Intel spec. must also cause a VM-exit. This prevents unpredictable behavior
854 * when future CPUs specify and use currently reserved/unspecified bits.
855 */
856 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
857 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
858 * and @bugref{6944}. */
859 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
860 return ( X86_CR0_PE
861 | X86_CR0_NE
862 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
863 | X86_CR0_PG
864 | VMX_EXIT_HOST_CR0_IGNORE_MASK);
865}
866
867
868/**
869 * Gets the CR4 guest/host mask.
870 *
871 * These bits typically does not change through the lifetime of a VM. Any bit set in
872 * this mask is owned by the host/hypervisor and would cause a VM-exit when modified
873 * by the guest.
874 *
875 * @returns The CR4 guest/host mask.
876 * @param pVCpu The cross context virtual CPU structure.
877 */
878static uint64_t hmR0VmxGetFixedCr4Mask(PCVMCPUCC pVCpu)
879{
880 /*
881 * We construct a mask of all CR4 bits that the guest can modify without causing
882 * a VM-exit. Then invert this mask to obtain all CR4 bits that should cause
883 * a VM-exit when the guest attempts to modify them when executing using
884 * hardware-assisted VMX.
885 *
886 * When a feature is not exposed to the guest (and may be present on the host),
887 * we want to intercept guest modifications to the bit so we can emulate proper
888 * behavior (e.g., #GP).
889 *
890 * Furthermore, only modifications to those bits that don't require immediate
891 * emulation is allowed. For e.g., PCIDE is excluded because the behavior
892 * depends on CR3 which might not always be the guest value while executing
893 * using hardware-assisted VMX.
894 */
895 PCVMCC pVM = pVCpu->CTX_SUFF(pVM);
896 bool const fFsGsBase = pVM->cpum.ro.GuestFeatures.fFsGsBase;
897 bool const fXSaveRstor = pVM->cpum.ro.GuestFeatures.fXSaveRstor;
898 bool const fFxSaveRstor = pVM->cpum.ro.GuestFeatures.fFxSaveRstor;
899
900 /*
901 * Paranoia.
902 * Ensure features exposed to the guest are present on the host.
903 */
904 Assert(!fFsGsBase || pVM->cpum.ro.HostFeatures.fFsGsBase);
905 Assert(!fXSaveRstor || pVM->cpum.ro.HostFeatures.fXSaveRstor);
906 Assert(!fFxSaveRstor || pVM->cpum.ro.HostFeatures.fFxSaveRstor);
907
908 uint64_t const fGstMask = ( X86_CR4_PVI
909 | X86_CR4_TSD
910 | X86_CR4_DE
911 | X86_CR4_MCE
912 | X86_CR4_PCE
913 | X86_CR4_OSXMMEEXCPT
914 | (fFsGsBase ? X86_CR4_FSGSBASE : 0)
915 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
916 | (fFxSaveRstor ? X86_CR4_OSFXSR : 0));
917 return ~fGstMask;
918}
919
920
921/**
922 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
923 * area.
924 *
925 * @returns @c true if it's different, @c false otherwise.
926 * @param pVmcsInfo The VMCS info. object.
927 */
928DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
929{
930 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
931 && pVmcsInfo->pvGuestMsrStore);
932}
933
934
935/**
936 * Sets the given Processor-based VM-execution controls.
937 *
938 * @param pVmxTransient The VMX-transient structure.
939 * @param uProcCtls The Processor-based VM-execution controls to set.
940 */
941static void hmR0VmxSetProcCtlsVmcs(PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
942{
943 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
944 if ((pVmcsInfo->u32ProcCtls & uProcCtls) != uProcCtls)
945 {
946 pVmcsInfo->u32ProcCtls |= uProcCtls;
947 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
948 AssertRC(rc);
949 }
950}
951
952
953/**
954 * Removes the given Processor-based VM-execution controls.
955 *
956 * @param pVCpu The cross context virtual CPU structure.
957 * @param pVmxTransient The VMX-transient structure.
958 * @param uProcCtls The Processor-based VM-execution controls to remove.
959 *
960 * @remarks When executing a nested-guest, this will not remove any of the specified
961 * controls if the nested hypervisor has set any one of them.
962 */
963static void hmR0VmxRemoveProcCtlsVmcs(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
964{
965 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
966 if (pVmcsInfo->u32ProcCtls & uProcCtls)
967 {
968#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
969 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
970 ? true
971 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uProcCtls);
972#else
973 NOREF(pVCpu);
974 bool const fRemoveCtls = true;
975#endif
976 if (fRemoveCtls)
977 {
978 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
979 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
980 AssertRC(rc);
981 }
982 }
983}
984
985
986/**
987 * Sets the TSC offset for the current VMCS.
988 *
989 * @param uTscOffset The TSC offset to set.
990 * @param pVmcsInfo The VMCS info. object.
991 */
992static void hmR0VmxSetTscOffsetVmcs(PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
993{
994 if (pVmcsInfo->u64TscOffset != uTscOffset)
995 {
996 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, uTscOffset);
997 AssertRC(rc);
998 pVmcsInfo->u64TscOffset = uTscOffset;
999 }
1000}
1001
1002
1003/**
1004 * Adds one or more exceptions to the exception bitmap and commits it to the current
1005 * VMCS.
1006 *
1007 * @param pVmxTransient The VMX-transient structure.
1008 * @param uXcptMask The exception(s) to add.
1009 */
1010static void hmR0VmxAddXcptInterceptMask(PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1011{
1012 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1013 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1014 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1015 {
1016 uXcptBitmap |= uXcptMask;
1017 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1018 AssertRC(rc);
1019 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1020 }
1021}
1022
1023
1024/**
1025 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1026 *
1027 * @param pVmxTransient The VMX-transient structure.
1028 * @param uXcpt The exception to add.
1029 */
1030static void hmR0VmxAddXcptIntercept(PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1031{
1032 Assert(uXcpt <= X86_XCPT_LAST);
1033 hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1034}
1035
1036
1037/**
1038 * Remove one or more exceptions from the exception bitmap and commits it to the
1039 * current VMCS.
1040 *
1041 * This takes care of not removing the exception intercept if a nested-guest
1042 * requires the exception to be intercepted.
1043 *
1044 * @returns VBox status code.
1045 * @param pVCpu The cross context virtual CPU structure.
1046 * @param pVmxTransient The VMX-transient structure.
1047 * @param uXcptMask The exception(s) to remove.
1048 */
1049static int hmR0VmxRemoveXcptInterceptMask(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1050{
1051 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1052 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1053 if (u32XcptBitmap & uXcptMask)
1054 {
1055#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1056 if (!pVmxTransient->fIsNestedGuest)
1057 { /* likely */ }
1058 else
1059 {
1060 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1061 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1062 }
1063#endif
1064#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1065 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1066 | RT_BIT(X86_XCPT_DE)
1067 | RT_BIT(X86_XCPT_NM)
1068 | RT_BIT(X86_XCPT_TS)
1069 | RT_BIT(X86_XCPT_UD)
1070 | RT_BIT(X86_XCPT_NP)
1071 | RT_BIT(X86_XCPT_SS)
1072 | RT_BIT(X86_XCPT_GP)
1073 | RT_BIT(X86_XCPT_PF)
1074 | RT_BIT(X86_XCPT_MF));
1075#elif defined(HMVMX_ALWAYS_TRAP_PF)
1076 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1077#endif
1078 if (uXcptMask)
1079 {
1080 /* Validate we are not removing any essential exception intercepts. */
1081 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF)));
1082 NOREF(pVCpu);
1083 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1084 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1085
1086 /* Remove it from the exception bitmap. */
1087 u32XcptBitmap &= ~uXcptMask;
1088
1089 /* Commit and update the cache if necessary. */
1090 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1091 {
1092 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1093 AssertRC(rc);
1094 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1095 }
1096 }
1097 }
1098 return VINF_SUCCESS;
1099}
1100
1101
1102/**
1103 * Remove an exceptions from the exception bitmap and commits it to the current
1104 * VMCS.
1105 *
1106 * @returns VBox status code.
1107 * @param pVCpu The cross context virtual CPU structure.
1108 * @param pVmxTransient The VMX-transient structure.
1109 * @param uXcpt The exception to remove.
1110 */
1111static int hmR0VmxRemoveXcptIntercept(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1112{
1113 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1114}
1115
1116
1117/**
1118 * Loads the VMCS specified by the VMCS info. object.
1119 *
1120 * @returns VBox status code.
1121 * @param pVmcsInfo The VMCS info. object.
1122 *
1123 * @remarks Can be called with interrupts disabled.
1124 */
1125static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1126{
1127 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1128 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1129
1130 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1131 if (RT_SUCCESS(rc))
1132 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1133 return rc;
1134}
1135
1136
1137/**
1138 * Clears the VMCS specified by the VMCS info. object.
1139 *
1140 * @returns VBox status code.
1141 * @param pVmcsInfo The VMCS info. object.
1142 *
1143 * @remarks Can be called with interrupts disabled.
1144 */
1145static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1146{
1147 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1148 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1149
1150 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1151 if (RT_SUCCESS(rc))
1152 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1153 return rc;
1154}
1155
1156
1157#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1158/**
1159 * Loads the shadow VMCS specified by the VMCS info. object.
1160 *
1161 * @returns VBox status code.
1162 * @param pVmcsInfo The VMCS info. object.
1163 *
1164 * @remarks Can be called with interrupts disabled.
1165 */
1166static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1167{
1168 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1169 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1170
1171 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1172 if (RT_SUCCESS(rc))
1173 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1174 return rc;
1175}
1176
1177
1178/**
1179 * Clears the shadow VMCS specified by the VMCS info. object.
1180 *
1181 * @returns VBox status code.
1182 * @param pVmcsInfo The VMCS info. object.
1183 *
1184 * @remarks Can be called with interrupts disabled.
1185 */
1186static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1187{
1188 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1189 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1190
1191 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1192 if (RT_SUCCESS(rc))
1193 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1194 return rc;
1195}
1196
1197
1198/**
1199 * Switches from and to the specified VMCSes.
1200 *
1201 * @returns VBox status code.
1202 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1203 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1204 *
1205 * @remarks Called with interrupts disabled.
1206 */
1207static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1208{
1209 /*
1210 * Clear the VMCS we are switching out if it has not already been cleared.
1211 * This will sync any CPU internal data back to the VMCS.
1212 */
1213 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1214 {
1215 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1216 if (RT_SUCCESS(rc))
1217 {
1218 /*
1219 * The shadow VMCS, if any, would not be active at this point since we
1220 * would have cleared it while importing the virtual hardware-virtualization
1221 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1222 * clear the shadow VMCS here, just assert for safety.
1223 */
1224 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1225 }
1226 else
1227 return rc;
1228 }
1229
1230 /*
1231 * Clear the VMCS we are switching to if it has not already been cleared.
1232 * This will initialize the VMCS launch state to "clear" required for loading it.
1233 *
1234 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1235 */
1236 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1237 {
1238 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1239 if (RT_SUCCESS(rc))
1240 { /* likely */ }
1241 else
1242 return rc;
1243 }
1244
1245 /*
1246 * Finally, load the VMCS we are switching to.
1247 */
1248 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1249}
1250
1251
1252/**
1253 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1254 * caller.
1255 *
1256 * @returns VBox status code.
1257 * @param pVCpu The cross context virtual CPU structure.
1258 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1259 * true) or guest VMCS (pass false).
1260 */
1261static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPUCC pVCpu, bool fSwitchToNstGstVmcs)
1262{
1263 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1264 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1265
1266 PVMXVMCSINFO pVmcsInfoFrom;
1267 PVMXVMCSINFO pVmcsInfoTo;
1268 if (fSwitchToNstGstVmcs)
1269 {
1270 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1271 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1272 }
1273 else
1274 {
1275 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1276 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1277 }
1278
1279 /*
1280 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1281 * preemption hook code path acquires the current VMCS.
1282 */
1283 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1284
1285 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1286 if (RT_SUCCESS(rc))
1287 {
1288 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1289
1290 /*
1291 * If we are switching to a VMCS that was executed on a different host CPU or was
1292 * never executed before, flag that we need to export the host state before executing
1293 * guest/nested-guest code using hardware-assisted VMX.
1294 *
1295 * This could probably be done in a preemptible context since the preemption hook
1296 * will flag the necessary change in host context. However, since preemption is
1297 * already disabled and to avoid making assumptions about host specific code in
1298 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1299 * disabled.
1300 */
1301 if (pVmcsInfoTo->idHostCpuState == RTMpCpuId())
1302 { /* likely */ }
1303 else
1304 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1305
1306 ASMSetFlags(fEFlags);
1307
1308 /*
1309 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1310 * flag that we need to update the host MSR values there. Even if we decide in the
1311 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1312 * if its content differs, we would have to update the host MSRs anyway.
1313 */
1314 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1315 }
1316 else
1317 ASMSetFlags(fEFlags);
1318 return rc;
1319}
1320#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1321
1322
1323/**
1324 * Updates the VM's last error record.
1325 *
1326 * If there was a VMX instruction error, reads the error data from the VMCS and
1327 * updates VCPU's last error record as well.
1328 *
1329 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1330 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1331 * VERR_VMX_INVALID_VMCS_FIELD.
1332 * @param rc The error code.
1333 */
1334static void hmR0VmxUpdateErrorRecord(PVMCPUCC pVCpu, int rc)
1335{
1336 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1337 || rc == VERR_VMX_UNABLE_TO_START_VM)
1338 {
1339 AssertPtrReturnVoid(pVCpu);
1340 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1341 }
1342 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1343}
1344
1345
1346#ifdef VBOX_STRICT
1347/**
1348 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1349 * transient structure.
1350 *
1351 * @param pVmxTransient The VMX-transient structure.
1352 */
1353DECLINLINE(void) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1354{
1355 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1356 AssertRC(rc);
1357}
1358
1359
1360/**
1361 * Reads the VM-entry exception error code field from the VMCS into
1362 * the VMX transient structure.
1363 *
1364 * @param pVmxTransient The VMX-transient structure.
1365 */
1366DECLINLINE(void) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1367{
1368 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1369 AssertRC(rc);
1370}
1371
1372
1373/**
1374 * Reads the VM-entry exception error code field from the VMCS into
1375 * the VMX transient structure.
1376 *
1377 * @param pVmxTransient The VMX-transient structure.
1378 */
1379DECLINLINE(void) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1380{
1381 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1382 AssertRC(rc);
1383}
1384#endif /* VBOX_STRICT */
1385
1386
1387/**
1388 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1389 * transient structure.
1390 *
1391 * @param pVmxTransient The VMX-transient structure.
1392 */
1393DECLINLINE(void) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1394{
1395 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1396 {
1397 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1398 AssertRC(rc);
1399 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1400 }
1401}
1402
1403
1404/**
1405 * Reads the VM-exit interruption error code from the VMCS into the VMX
1406 * transient structure.
1407 *
1408 * @param pVmxTransient The VMX-transient structure.
1409 */
1410DECLINLINE(void) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1411{
1412 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1413 {
1414 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1415 AssertRC(rc);
1416 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1417 }
1418}
1419
1420
1421/**
1422 * Reads the VM-exit instruction length field from the VMCS into the VMX
1423 * transient structure.
1424 *
1425 * @param pVmxTransient The VMX-transient structure.
1426 */
1427DECLINLINE(void) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1428{
1429 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1430 {
1431 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1432 AssertRC(rc);
1433 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1434 }
1435}
1436
1437
1438/**
1439 * Reads the VM-exit instruction-information field from the VMCS into
1440 * the VMX transient structure.
1441 *
1442 * @param pVmxTransient The VMX-transient structure.
1443 */
1444DECLINLINE(void) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1445{
1446 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1447 {
1448 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1449 AssertRC(rc);
1450 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1451 }
1452}
1453
1454
1455/**
1456 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1457 *
1458 * @param pVmxTransient The VMX-transient structure.
1459 */
1460DECLINLINE(void) hmR0VmxReadExitQualVmcs(PVMXTRANSIENT pVmxTransient)
1461{
1462 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1463 {
1464 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1465 AssertRC(rc);
1466 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1467 }
1468}
1469
1470
1471/**
1472 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1473 *
1474 * @param pVmxTransient The VMX-transient structure.
1475 */
1476DECLINLINE(void) hmR0VmxReadGuestLinearAddrVmcs(PVMXTRANSIENT pVmxTransient)
1477{
1478 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1479 {
1480 int rc = VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1481 AssertRC(rc);
1482 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1483 }
1484}
1485
1486
1487/**
1488 * Reads the Guest-physical address from the VMCS into the VMX transient structure.
1489 *
1490 * @param pVmxTransient The VMX-transient structure.
1491 */
1492DECLINLINE(void) hmR0VmxReadGuestPhysicalAddrVmcs(PVMXTRANSIENT pVmxTransient)
1493{
1494 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PHYSICAL_ADDR))
1495 {
1496 int rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1497 AssertRC(rc);
1498 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PHYSICAL_ADDR;
1499 }
1500}
1501
1502#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1503/**
1504 * Reads the Guest pending-debug exceptions from the VMCS into the VMX transient
1505 * structure.
1506 *
1507 * @param pVmxTransient The VMX-transient structure.
1508 */
1509DECLINLINE(void) hmR0VmxReadGuestPendingDbgXctps(PVMXTRANSIENT pVmxTransient)
1510{
1511 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_PENDING_DBG_XCPTS))
1512 {
1513 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &pVmxTransient->uGuestPendingDbgXcpts);
1514 AssertRC(rc);
1515 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_PENDING_DBG_XCPTS;
1516 }
1517}
1518#endif
1519
1520/**
1521 * Reads the IDT-vectoring information field from the VMCS into the VMX
1522 * transient structure.
1523 *
1524 * @param pVmxTransient The VMX-transient structure.
1525 *
1526 * @remarks No-long-jump zone!!!
1527 */
1528DECLINLINE(void) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1529{
1530 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1531 {
1532 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1533 AssertRC(rc);
1534 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1535 }
1536}
1537
1538
1539/**
1540 * Reads the IDT-vectoring error code from the VMCS into the VMX
1541 * transient structure.
1542 *
1543 * @param pVmxTransient The VMX-transient structure.
1544 */
1545DECLINLINE(void) hmR0VmxReadIdtVectoringErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1546{
1547 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_ERROR_CODE))
1548 {
1549 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1550 AssertRC(rc);
1551 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1552 }
1553}
1554
1555#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
1556/**
1557 * Reads all relevant read-only VMCS fields into the VMX transient structure.
1558 *
1559 * @param pVmxTransient The VMX-transient structure.
1560 */
1561static void hmR0VmxReadAllRoFieldsVmcs(PVMXTRANSIENT pVmxTransient)
1562{
1563 int rc = VMXReadVmcsNw(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual);
1564 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbExitInstr);
1565 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1566 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1567 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pVmxTransient->uIdtVectoringErrorCode);
1568 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1569 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1570 rc |= VMXReadVmcsNw(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr);
1571 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pVmxTransient->uGuestPhysicalAddr);
1572 AssertRC(rc);
1573 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION
1574 | HMVMX_READ_EXIT_INSTR_LEN
1575 | HMVMX_READ_EXIT_INSTR_INFO
1576 | HMVMX_READ_IDT_VECTORING_INFO
1577 | HMVMX_READ_IDT_VECTORING_ERROR_CODE
1578 | HMVMX_READ_EXIT_INTERRUPTION_INFO
1579 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE
1580 | HMVMX_READ_GUEST_LINEAR_ADDR
1581 | HMVMX_READ_GUEST_PHYSICAL_ADDR;
1582}
1583#endif
1584
1585/**
1586 * Enters VMX root mode operation on the current CPU.
1587 *
1588 * @returns VBox status code.
1589 * @param pHostCpu The HM physical-CPU structure.
1590 * @param pVM The cross context VM structure. Can be
1591 * NULL, after a resume.
1592 * @param HCPhysCpuPage Physical address of the VMXON region.
1593 * @param pvCpuPage Pointer to the VMXON region.
1594 */
1595static int hmR0VmxEnterRootMode(PHMPHYSCPU pHostCpu, PVMCC pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1596{
1597 Assert(pHostCpu);
1598 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1599 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1600 Assert(pvCpuPage);
1601 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1602
1603 if (pVM)
1604 {
1605 /* Write the VMCS revision identifier to the VMXON region. */
1606 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1607 }
1608
1609 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1610 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1611
1612 /* Enable the VMX bit in CR4 if necessary. */
1613 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1614
1615 /* Record whether VMXE was already prior to us enabling it above. */
1616 pHostCpu->fVmxeAlreadyEnabled = RT_BOOL(uOldCr4 & X86_CR4_VMXE);
1617
1618 /* Enter VMX root mode. */
1619 int rc = VMXEnable(HCPhysCpuPage);
1620 if (RT_FAILURE(rc))
1621 {
1622 /* Restore CR4.VMXE if it was not set prior to our attempt to set it above. */
1623 if (!pHostCpu->fVmxeAlreadyEnabled)
1624 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1625
1626 if (pVM)
1627 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1628 }
1629
1630 /* Restore interrupts. */
1631 ASMSetFlags(fEFlags);
1632 return rc;
1633}
1634
1635
1636/**
1637 * Exits VMX root mode operation on the current CPU.
1638 *
1639 * @returns VBox status code.
1640 * @param pHostCpu The HM physical-CPU structure.
1641 */
1642static int hmR0VmxLeaveRootMode(PHMPHYSCPU pHostCpu)
1643{
1644 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1645
1646 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1647 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1648
1649 /* If we're for some reason not in VMX root mode, then don't leave it. */
1650 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1651
1652 int rc;
1653 if (uHostCr4 & X86_CR4_VMXE)
1654 {
1655 /* Exit VMX root mode and clear the VMX bit in CR4. */
1656 VMXDisable();
1657
1658 /* Clear CR4.VMXE only if it was clear prior to use setting it. */
1659 if (!pHostCpu->fVmxeAlreadyEnabled)
1660 SUPR0ChangeCR4(0 /* fOrMask */, ~(uint64_t)X86_CR4_VMXE);
1661
1662 rc = VINF_SUCCESS;
1663 }
1664 else
1665 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1666
1667 /* Restore interrupts. */
1668 ASMSetFlags(fEFlags);
1669 return rc;
1670}
1671
1672
1673/**
1674 * Allocates and maps a physically contiguous page. The allocated page is
1675 * zero'd out (used by various VT-x structures).
1676 *
1677 * @returns IPRT status code.
1678 * @param pMemObj Pointer to the ring-0 memory object.
1679 * @param ppVirt Where to store the virtual address of the allocation.
1680 * @param pHCPhys Where to store the physical address of the allocation.
1681 */
1682static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1683{
1684 AssertPtr(pMemObj);
1685 AssertPtr(ppVirt);
1686 AssertPtr(pHCPhys);
1687 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1688 if (RT_FAILURE(rc))
1689 return rc;
1690 *ppVirt = RTR0MemObjAddress(*pMemObj);
1691 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1692 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1693 return VINF_SUCCESS;
1694}
1695
1696
1697/**
1698 * Frees and unmaps an allocated, physical page.
1699 *
1700 * @param pMemObj Pointer to the ring-0 memory object.
1701 * @param ppVirt Where to re-initialize the virtual address of allocation as
1702 * 0.
1703 * @param pHCPhys Where to re-initialize the physical address of the
1704 * allocation as 0.
1705 */
1706static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1707{
1708 AssertPtr(pMemObj);
1709 AssertPtr(ppVirt);
1710 AssertPtr(pHCPhys);
1711 /* NULL is valid, accepted and ignored by the free function below. */
1712 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1713 *pMemObj = NIL_RTR0MEMOBJ;
1714 *ppVirt = NULL;
1715 *pHCPhys = NIL_RTHCPHYS;
1716}
1717
1718
1719/**
1720 * Initializes a VMCS info. object.
1721 *
1722 * @param pVmcsInfo The VMCS info. object.
1723 */
1724static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1725{
1726 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1727
1728 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1729 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1730 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1731 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1732 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1733 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1734 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1735 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1736 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1737 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1738 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1739 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1740 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1741 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1742 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1743 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
1744 pVmcsInfo->idHostCpuExec = NIL_RTCPUID;
1745}
1746
1747
1748/**
1749 * Frees the VT-x structures for a VMCS info. object.
1750 *
1751 * @param pVM The cross context VM structure.
1752 * @param pVmcsInfo The VMCS info. object.
1753 */
1754static void hmR0VmxFreeVmcsInfo(PVMCC pVM, PVMXVMCSINFO pVmcsInfo)
1755{
1756 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1757
1758#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1759 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1760 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1761#endif
1762
1763 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1764 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1765
1766 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1767 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1768 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1769
1770 hmR0VmxInitVmcsInfo(pVmcsInfo);
1771}
1772
1773
1774/**
1775 * Allocates the VT-x structures for a VMCS info. object.
1776 *
1777 * @returns VBox status code.
1778 * @param pVCpu The cross context virtual CPU structure.
1779 * @param pVmcsInfo The VMCS info. object.
1780 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1781 */
1782static int hmR0VmxAllocVmcsInfo(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1783{
1784 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
1785
1786 /* Allocate the guest VM control structure (VMCS). */
1787 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1788 if (RT_SUCCESS(rc))
1789 {
1790 if (!fIsNstGstVmcs)
1791 {
1792#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1793 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1794 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1795#endif
1796 if (RT_SUCCESS(rc))
1797 {
1798 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1799 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1800 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1801 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic, NULL /*pR3Ptr*/);
1802 }
1803 }
1804 else
1805 {
1806 /* We don't yet support exposing VMCS shadowing to the guest. */
1807 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1808 Assert(!pVmcsInfo->pvShadowVmcs);
1809
1810 /* Get the allocated virtual-APIC page from CPUM. */
1811 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1812 {
1813 /** @todo NSTVMX: Get rid of this. There is no need to allocate a separate HC
1814 * page for this. Use the one provided by the nested-guest directly. */
1815 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1816 &pVmcsInfo->HCPhysVirtApic);
1817 Assert(pVmcsInfo->pbVirtApic);
1818 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1819 }
1820 }
1821
1822 if (RT_SUCCESS(rc))
1823 {
1824 /*
1825 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1826 * transparent accesses of specific MSRs.
1827 *
1828 * If the condition for enabling MSR bitmaps changes here, don't forget to
1829 * update HMIsMsrBitmapActive().
1830 *
1831 * We don't share MSR bitmaps between the guest and nested-guest as we then
1832 * don't need to care about carefully restoring the guest MSR bitmap.
1833 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1834 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1835 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1836 * we do that later while merging VMCS.
1837 */
1838 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1839 {
1840 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1841 if ( RT_SUCCESS(rc)
1842 && !fIsNstGstVmcs)
1843 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1844 }
1845
1846 if (RT_SUCCESS(rc))
1847 {
1848 /*
1849 * Allocate the VM-entry MSR-load area for the guest MSRs.
1850 *
1851 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1852 * the guest and nested-guest.
1853 */
1854 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1855 &pVmcsInfo->HCPhysGuestMsrLoad);
1856 if (RT_SUCCESS(rc))
1857 {
1858 /*
1859 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1860 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1861 */
1862 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1863 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1864 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1865
1866 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1867 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1868 &pVmcsInfo->HCPhysHostMsrLoad);
1869 }
1870 }
1871 }
1872 }
1873
1874 return rc;
1875}
1876
1877
1878/**
1879 * Free all VT-x structures for the VM.
1880 *
1881 * @returns IPRT status code.
1882 * @param pVM The cross context VM structure.
1883 */
1884static void hmR0VmxStructsFree(PVMCC pVM)
1885{
1886#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1887 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1888#endif
1889 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1890
1891#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1892 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1893 {
1894 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1895 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1896 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1897 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1898 }
1899#endif
1900
1901 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1902 {
1903 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1904 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1905 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1906#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1907 if (pVM->cpum.ro.GuestFeatures.fVmx)
1908 {
1909 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1910 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1911 }
1912#endif
1913 }
1914}
1915
1916
1917/**
1918 * Allocate all VT-x structures for the VM.
1919 *
1920 * @returns IPRT status code.
1921 * @param pVM The cross context VM structure.
1922 */
1923static int hmR0VmxStructsAlloc(PVMCC pVM)
1924{
1925 /*
1926 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1927 * The VMCS size cannot be more than 4096 bytes.
1928 *
1929 * See Intel spec. Appendix A.1 "Basic VMX Information".
1930 */
1931 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1932 if (cbVmcs <= X86_PAGE_4K_SIZE)
1933 { /* likely */ }
1934 else
1935 {
1936 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1937 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1938 }
1939
1940 /*
1941 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1942 */
1943#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1944 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1945 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1946 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1947#endif
1948
1949 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1950 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1951 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1952
1953 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1954 {
1955 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
1956 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1957 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1958 }
1959
1960 /*
1961 * Allocate per-VM VT-x structures.
1962 */
1963 int rc = VINF_SUCCESS;
1964#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1965 /* Allocate crash-dump magic scratch page. */
1966 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1967 if (RT_FAILURE(rc))
1968 {
1969 hmR0VmxStructsFree(pVM);
1970 return rc;
1971 }
1972 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1973 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1974#endif
1975
1976 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1977 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1978 {
1979 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1980 &pVM->hm.s.vmx.HCPhysApicAccess);
1981 if (RT_FAILURE(rc))
1982 {
1983 hmR0VmxStructsFree(pVM);
1984 return rc;
1985 }
1986 }
1987
1988#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1989 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1990 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1991 {
1992 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1993 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1994 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1995 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1996 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1997 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1998 {
1999 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
2000 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
2001 if (RT_SUCCESS(rc))
2002 {
2003 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
2004 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
2005 }
2006 }
2007 else
2008 rc = VERR_NO_MEMORY;
2009
2010 if (RT_FAILURE(rc))
2011 {
2012 hmR0VmxStructsFree(pVM);
2013 return rc;
2014 }
2015 }
2016#endif
2017
2018 /*
2019 * Initialize per-VCPU VT-x structures.
2020 */
2021 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
2022 {
2023 /* Allocate the guest VMCS structures. */
2024 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
2025 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
2026 if (RT_SUCCESS(rc))
2027 {
2028#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2029 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
2030 if (pVM->cpum.ro.GuestFeatures.fVmx)
2031 {
2032 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
2033 if (RT_SUCCESS(rc))
2034 { /* likely */ }
2035 else
2036 break;
2037 }
2038#endif
2039 }
2040 else
2041 break;
2042 }
2043
2044 if (RT_FAILURE(rc))
2045 {
2046 hmR0VmxStructsFree(pVM);
2047 return rc;
2048 }
2049
2050 return VINF_SUCCESS;
2051}
2052
2053#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2054/**
2055 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2056 *
2057 * @returns @c true if the MSR is intercepted, @c false otherwise.
2058 * @param pvMsrBitmap The MSR bitmap.
2059 * @param offMsr The MSR byte offset.
2060 * @param iBit The bit offset from the byte offset.
2061 */
2062DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2063{
2064 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2065 Assert(pbMsrBitmap);
2066 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2067 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2068}
2069#endif
2070
2071/**
2072 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2073 *
2074 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2075 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2076 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2077 * the read/write access of this MSR.
2078 *
2079 * @param pVCpu The cross context virtual CPU structure.
2080 * @param pVmcsInfo The VMCS info. object.
2081 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2082 * @param idMsr The MSR value.
2083 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2084 * include both a read -and- a write permission!
2085 *
2086 * @sa CPUMGetVmxMsrPermission.
2087 * @remarks Can be called with interrupts disabled.
2088 */
2089static void hmR0VmxSetMsrPermission(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2090{
2091 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2092 Assert(pbMsrBitmap);
2093 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2094
2095 /*
2096 * MSR-bitmap Layout:
2097 * Byte index MSR range Interpreted as
2098 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2099 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2100 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2101 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2102 *
2103 * A bit corresponding to an MSR within the above range causes a VM-exit
2104 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2105 * the MSR range, it always cause a VM-exit.
2106 *
2107 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2108 */
2109 uint16_t const offBitmapRead = 0;
2110 uint16_t const offBitmapWrite = 0x800;
2111 uint16_t offMsr;
2112 int32_t iBit;
2113 if (idMsr <= UINT32_C(0x00001fff))
2114 {
2115 offMsr = 0;
2116 iBit = idMsr;
2117 }
2118 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2119 {
2120 offMsr = 0x400;
2121 iBit = idMsr - UINT32_C(0xc0000000);
2122 }
2123 else
2124 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2125
2126 /*
2127 * Set the MSR read permission.
2128 */
2129 uint16_t const offMsrRead = offBitmapRead + offMsr;
2130 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2131 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2132 {
2133#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2134 bool const fClear = !fIsNstGstVmcs ? true
2135 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2136#else
2137 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2138 bool const fClear = true;
2139#endif
2140 if (fClear)
2141 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2142 }
2143 else
2144 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2145
2146 /*
2147 * Set the MSR write permission.
2148 */
2149 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2150 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2151 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2152 {
2153#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2154 bool const fClear = !fIsNstGstVmcs ? true
2155 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2156#else
2157 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2158 bool const fClear = true;
2159#endif
2160 if (fClear)
2161 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2162 }
2163 else
2164 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2165}
2166
2167
2168/**
2169 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2170 * area.
2171 *
2172 * @returns VBox status code.
2173 * @param pVCpu The cross context virtual CPU structure.
2174 * @param pVmcsInfo The VMCS info. object.
2175 * @param cMsrs The number of MSRs.
2176 */
2177static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2178{
2179 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2180 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2181 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2182 {
2183 /* Commit the MSR counts to the VMCS and update the cache. */
2184 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2185 {
2186 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2187 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs); AssertRC(rc);
2188 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs); AssertRC(rc);
2189 pVmcsInfo->cEntryMsrLoad = cMsrs;
2190 pVmcsInfo->cExitMsrStore = cMsrs;
2191 pVmcsInfo->cExitMsrLoad = cMsrs;
2192 }
2193 return VINF_SUCCESS;
2194 }
2195
2196 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2197 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2198 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2199}
2200
2201
2202/**
2203 * Adds a new (or updates the value of an existing) guest/host MSR
2204 * pair to be swapped during the world-switch as part of the
2205 * auto-load/store MSR area in the VMCS.
2206 *
2207 * @returns VBox status code.
2208 * @param pVCpu The cross context virtual CPU structure.
2209 * @param pVmxTransient The VMX-transient structure.
2210 * @param idMsr The MSR.
2211 * @param uGuestMsrValue Value of the guest MSR.
2212 * @param fSetReadWrite Whether to set the guest read/write access of this
2213 * MSR (thus not causing a VM-exit).
2214 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2215 * necessary.
2216 */
2217static int hmR0VmxAddAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2218 bool fSetReadWrite, bool fUpdateHostMsr)
2219{
2220 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2221 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2222 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2223 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2224 uint32_t i;
2225
2226 /* Paranoia. */
2227 Assert(pGuestMsrLoad);
2228
2229 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2230
2231 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2232 for (i = 0; i < cMsrs; i++)
2233 {
2234 if (pGuestMsrLoad[i].u32Msr == idMsr)
2235 break;
2236 }
2237
2238 bool fAdded = false;
2239 if (i == cMsrs)
2240 {
2241 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2242 ++cMsrs;
2243 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2244 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2245
2246 /* Set the guest to read/write this MSR without causing VM-exits. */
2247 if ( fSetReadWrite
2248 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2249 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2250
2251 Log4Func(("Added MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2252 fAdded = true;
2253 }
2254
2255 /* Update the MSR value for the newly added or already existing MSR. */
2256 pGuestMsrLoad[i].u32Msr = idMsr;
2257 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2258
2259 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2260 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2261 {
2262 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2263 pGuestMsrStore[i].u32Msr = idMsr;
2264 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2265 }
2266
2267 /* Update the corresponding slot in the host MSR area. */
2268 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2269 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2270 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2271 pHostMsr[i].u32Msr = idMsr;
2272
2273 /*
2274 * Only if the caller requests to update the host MSR value AND we've newly added the
2275 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2276 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2277 *
2278 * We do this for performance reasons since reading MSRs may be quite expensive.
2279 */
2280 if (fAdded)
2281 {
2282 if (fUpdateHostMsr)
2283 {
2284 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2285 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2286 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2287 }
2288 else
2289 {
2290 /* Someone else can do the work. */
2291 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2292 }
2293 }
2294 return VINF_SUCCESS;
2295}
2296
2297
2298/**
2299 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2300 * auto-load/store MSR area in the VMCS.
2301 *
2302 * @returns VBox status code.
2303 * @param pVCpu The cross context virtual CPU structure.
2304 * @param pVmxTransient The VMX-transient structure.
2305 * @param idMsr The MSR.
2306 */
2307static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2308{
2309 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2310 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2311 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2312 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2313
2314 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2315
2316 for (uint32_t i = 0; i < cMsrs; i++)
2317 {
2318 /* Find the MSR. */
2319 if (pGuestMsrLoad[i].u32Msr == idMsr)
2320 {
2321 /*
2322 * If it's the last MSR, we only need to reduce the MSR count.
2323 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2324 */
2325 if (i < cMsrs - 1)
2326 {
2327 /* Remove it from the VM-entry MSR-load area. */
2328 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2329 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2330
2331 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2332 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2333 {
2334 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2335 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2336 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2337 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2338 }
2339
2340 /* Remove it from the VM-exit MSR-load area. */
2341 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2342 Assert(pHostMsr[i].u32Msr == idMsr);
2343 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2344 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2345 }
2346
2347 /* Reduce the count to reflect the removed MSR and bail. */
2348 --cMsrs;
2349 break;
2350 }
2351 }
2352
2353 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2354 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2355 {
2356 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2357 AssertRCReturn(rc, rc);
2358
2359 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2360 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2361 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2362
2363 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2364 return VINF_SUCCESS;
2365 }
2366
2367 return VERR_NOT_FOUND;
2368}
2369
2370
2371/**
2372 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2373 *
2374 * @returns @c true if found, @c false otherwise.
2375 * @param pVmcsInfo The VMCS info. object.
2376 * @param idMsr The MSR to find.
2377 */
2378static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2379{
2380 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2381 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2382 Assert(pMsrs);
2383 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2384 for (uint32_t i = 0; i < cMsrs; i++)
2385 {
2386 if (pMsrs[i].u32Msr == idMsr)
2387 return true;
2388 }
2389 return false;
2390}
2391
2392
2393/**
2394 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2395 *
2396 * @param pVCpu The cross context virtual CPU structure.
2397 * @param pVmcsInfo The VMCS info. object.
2398 *
2399 * @remarks No-long-jump zone!!!
2400 */
2401static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2402{
2403 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2404
2405 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2406 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2407 Assert(pHostMsrLoad);
2408 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2409 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2410 for (uint32_t i = 0; i < cMsrs; i++)
2411 {
2412 /*
2413 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2414 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2415 */
2416 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2417 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2418 else
2419 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2420 }
2421}
2422
2423
2424/**
2425 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2426 * perform lazy restoration of the host MSRs while leaving VT-x.
2427 *
2428 * @param pVCpu The cross context virtual CPU structure.
2429 *
2430 * @remarks No-long-jump zone!!!
2431 */
2432static void hmR0VmxLazySaveHostMsrs(PVMCPUCC pVCpu)
2433{
2434 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2435
2436 /*
2437 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2438 */
2439 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2440 {
2441 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2442 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2443 {
2444 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2445 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2446 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2447 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2448 }
2449 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2450 }
2451}
2452
2453
2454/**
2455 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2456 * lazily while leaving VT-x.
2457 *
2458 * @returns true if it does, false otherwise.
2459 * @param pVCpu The cross context virtual CPU structure.
2460 * @param idMsr The MSR to check.
2461 */
2462static bool hmR0VmxIsLazyGuestMsr(PCVMCPUCC pVCpu, uint32_t idMsr)
2463{
2464 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2465 {
2466 switch (idMsr)
2467 {
2468 case MSR_K8_LSTAR:
2469 case MSR_K6_STAR:
2470 case MSR_K8_SF_MASK:
2471 case MSR_K8_KERNEL_GS_BASE:
2472 return true;
2473 }
2474 }
2475 return false;
2476}
2477
2478
2479/**
2480 * Loads a set of guests MSRs to allow read/passthru to the guest.
2481 *
2482 * The name of this function is slightly confusing. This function does NOT
2483 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2484 * common prefix for functions dealing with "lazy restoration" of the shared
2485 * MSRs.
2486 *
2487 * @param pVCpu The cross context virtual CPU structure.
2488 *
2489 * @remarks No-long-jump zone!!!
2490 */
2491static void hmR0VmxLazyLoadGuestMsrs(PVMCPUCC pVCpu)
2492{
2493 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2494 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2495
2496 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2497 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2498 {
2499 /*
2500 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2501 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2502 * we can skip a few MSR writes.
2503 *
2504 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2505 * guest MSR values in the guest-CPU context might be different to what's currently
2506 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2507 * CPU, see @bugref{8728}.
2508 */
2509 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2510 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2511 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2512 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2513 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2514 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2515 {
2516#ifdef VBOX_STRICT
2517 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2518 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2519 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2520 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2521#endif
2522 }
2523 else
2524 {
2525 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2526 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2527 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2528 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2529 }
2530 }
2531 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2532}
2533
2534
2535/**
2536 * Performs lazy restoration of the set of host MSRs if they were previously
2537 * loaded with guest MSR values.
2538 *
2539 * @param pVCpu The cross context virtual CPU structure.
2540 *
2541 * @remarks No-long-jump zone!!!
2542 * @remarks The guest MSRs should have been saved back into the guest-CPU
2543 * context by hmR0VmxImportGuestState()!!!
2544 */
2545static void hmR0VmxLazyRestoreHostMsrs(PVMCPUCC pVCpu)
2546{
2547 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2548 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2549
2550 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2551 {
2552 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2553 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2554 {
2555 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2556 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2557 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2558 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2559 }
2560 }
2561 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2562}
2563
2564
2565/**
2566 * Verifies that our cached values of the VMCS fields are all consistent with
2567 * what's actually present in the VMCS.
2568 *
2569 * @returns VBox status code.
2570 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2571 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2572 * VMCS content. HMCPU error-field is
2573 * updated, see VMX_VCI_XXX.
2574 * @param pVCpu The cross context virtual CPU structure.
2575 * @param pVmcsInfo The VMCS info. object.
2576 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2577 */
2578static int hmR0VmxCheckVmcsCtls(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2579{
2580 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2581
2582 uint32_t u32Val;
2583 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2584 AssertRC(rc);
2585 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2586 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2587 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2588 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2589
2590 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2591 AssertRC(rc);
2592 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2593 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2594 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2595 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2596
2597 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2598 AssertRC(rc);
2599 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2600 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2601 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2602 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2603
2604 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2605 AssertRC(rc);
2606 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2607 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2608 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2609 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2610
2611 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2612 {
2613 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2614 AssertRC(rc);
2615 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2616 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2617 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2618 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2619 }
2620
2621 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2622 AssertRC(rc);
2623 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2624 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2625 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2626 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2627
2628 uint64_t u64Val;
2629 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2630 AssertRC(rc);
2631 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2632 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2633 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2634 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2635
2636 NOREF(pcszVmcs);
2637 return VINF_SUCCESS;
2638}
2639
2640
2641#ifdef VBOX_STRICT
2642/**
2643 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2644 *
2645 * @param pVCpu The cross context virtual CPU structure.
2646 * @param pVmcsInfo The VMCS info. object.
2647 */
2648static void hmR0VmxCheckHostEferMsr(PCVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2649{
2650 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2651
2652 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2653 {
2654 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2655 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2656 uint64_t uVmcsEferMsrVmcs;
2657 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2658 AssertRC(rc);
2659
2660 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2661 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2662 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2663 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2664 }
2665}
2666
2667
2668/**
2669 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2670 * VMCS are correct.
2671 *
2672 * @param pVCpu The cross context virtual CPU structure.
2673 * @param pVmcsInfo The VMCS info. object.
2674 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2675 */
2676static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2677{
2678 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2679
2680 /* Read the various MSR-area counts from the VMCS. */
2681 uint32_t cEntryLoadMsrs;
2682 uint32_t cExitStoreMsrs;
2683 uint32_t cExitLoadMsrs;
2684 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2685 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2686 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2687
2688 /* Verify all the MSR counts are the same. */
2689 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2690 Assert(cExitStoreMsrs == cExitLoadMsrs);
2691 uint32_t const cMsrs = cExitLoadMsrs;
2692
2693 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2694 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2695
2696 /* Verify the MSR counts are within the allocated page size. */
2697 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2698
2699 /* Verify the relevant contents of the MSR areas match. */
2700 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2701 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2702 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2703 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2704 for (uint32_t i = 0; i < cMsrs; i++)
2705 {
2706 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2707 if (fSeparateExitMsrStorePage)
2708 {
2709 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2710 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2711 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2712 }
2713
2714 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2715 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2716 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2717
2718 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2719 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2720 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2721 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2722
2723 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2724 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2725 if (fIsEferMsr)
2726 {
2727 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2728 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2729 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2730 }
2731
2732 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2733 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2734 {
2735 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2736 if (fIsEferMsr)
2737 {
2738 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2739 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2740 }
2741 else
2742 {
2743 if (!fIsNstGstVmcs)
2744 {
2745 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2746 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2747 }
2748 else
2749 {
2750 /*
2751 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2752 * execute a nested-guest with MSR passthrough.
2753 *
2754 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2755 * allow passthrough too.
2756 */
2757 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2758 Assert(pvMsrBitmapNstGst);
2759 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2760 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2761 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2762 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2763 }
2764 }
2765 }
2766
2767 /* Move to the next MSR. */
2768 pHostMsrLoad++;
2769 pGuestMsrLoad++;
2770 pGuestMsrStore++;
2771 }
2772}
2773#endif /* VBOX_STRICT */
2774
2775
2776/**
2777 * Flushes the TLB using EPT.
2778 *
2779 * @returns VBox status code.
2780 * @param pVCpu The cross context virtual CPU structure of the calling
2781 * EMT. Can be NULL depending on @a enmTlbFlush.
2782 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2783 * enmTlbFlush.
2784 * @param enmTlbFlush Type of flush.
2785 *
2786 * @remarks Caller is responsible for making sure this function is called only
2787 * when NestedPaging is supported and providing @a enmTlbFlush that is
2788 * supported by the CPU.
2789 * @remarks Can be called with interrupts disabled.
2790 */
2791static void hmR0VmxFlushEpt(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2792{
2793 uint64_t au64Descriptor[2];
2794 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2795 au64Descriptor[0] = 0;
2796 else
2797 {
2798 Assert(pVCpu);
2799 Assert(pVmcsInfo);
2800 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2801 }
2802 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2803
2804 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2805 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2806
2807 if ( RT_SUCCESS(rc)
2808 && pVCpu)
2809 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2810}
2811
2812
2813/**
2814 * Flushes the TLB using VPID.
2815 *
2816 * @returns VBox status code.
2817 * @param pVCpu The cross context virtual CPU structure of the calling
2818 * EMT. Can be NULL depending on @a enmTlbFlush.
2819 * @param enmTlbFlush Type of flush.
2820 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2821 * on @a enmTlbFlush).
2822 *
2823 * @remarks Can be called with interrupts disabled.
2824 */
2825static void hmR0VmxFlushVpid(PVMCPUCC pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2826{
2827 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2828
2829 uint64_t au64Descriptor[2];
2830 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2831 {
2832 au64Descriptor[0] = 0;
2833 au64Descriptor[1] = 0;
2834 }
2835 else
2836 {
2837 AssertPtr(pVCpu);
2838 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2839 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2840 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2841 au64Descriptor[1] = GCPtr;
2842 }
2843
2844 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2845 AssertMsg(rc == VINF_SUCCESS,
2846 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2847
2848 if ( RT_SUCCESS(rc)
2849 && pVCpu)
2850 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2851 NOREF(rc);
2852}
2853
2854
2855/**
2856 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2857 * otherwise there is nothing really to invalidate.
2858 *
2859 * @returns VBox status code.
2860 * @param pVCpu The cross context virtual CPU structure.
2861 * @param GCVirt Guest virtual address of the page to invalidate.
2862 */
2863VMMR0DECL(int) VMXR0InvalidatePage(PVMCPUCC pVCpu, RTGCPTR GCVirt)
2864{
2865 AssertPtr(pVCpu);
2866 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2867
2868 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2869 {
2870 /*
2871 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2872 * the EPT case. See @bugref{6043} and @bugref{6177}.
2873 *
2874 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2875 * as this function maybe called in a loop with individual addresses.
2876 */
2877 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2878 if (pVM->hm.s.vmx.fVpid)
2879 {
2880 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2881 if (fVpidFlush)
2882 {
2883 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2884 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2885 }
2886 else
2887 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2888 }
2889 else if (pVM->hm.s.fNestedPaging)
2890 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2891 }
2892
2893 return VINF_SUCCESS;
2894}
2895
2896
2897/**
2898 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2899 * case where neither EPT nor VPID is supported by the CPU.
2900 *
2901 * @param pHostCpu The HM physical-CPU structure.
2902 * @param pVCpu The cross context virtual CPU structure.
2903 *
2904 * @remarks Called with interrupts disabled.
2905 */
2906static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
2907{
2908 AssertPtr(pVCpu);
2909 AssertPtr(pHostCpu);
2910
2911 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2912
2913 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2914 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2915 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2916 pVCpu->hm.s.fForceTLBFlush = false;
2917 return;
2918}
2919
2920
2921/**
2922 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2923 *
2924 * @param pHostCpu The HM physical-CPU structure.
2925 * @param pVCpu The cross context virtual CPU structure.
2926 * @param pVmcsInfo The VMCS info. object.
2927 *
2928 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2929 * nomenclature. The reason is, to avoid confusion in compare statements
2930 * since the host-CPU copies are named "ASID".
2931 *
2932 * @remarks Called with interrupts disabled.
2933 */
2934static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
2935{
2936#ifdef VBOX_WITH_STATISTICS
2937 bool fTlbFlushed = false;
2938# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2939# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2940 if (!fTlbFlushed) \
2941 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2942 } while (0)
2943#else
2944# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2945# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2946#endif
2947
2948 AssertPtr(pVCpu);
2949 AssertPtr(pHostCpu);
2950 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2951
2952 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
2953 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2954 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2955 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2956
2957 /*
2958 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2959 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2960 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2961 * cannot reuse the current ASID anymore.
2962 */
2963 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2964 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2965 {
2966 ++pHostCpu->uCurrentAsid;
2967 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2968 {
2969 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2970 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2971 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2972 }
2973
2974 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2975 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2976 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2977
2978 /*
2979 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2980 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2981 */
2982 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2983 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2984 HMVMX_SET_TAGGED_TLB_FLUSHED();
2985 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2986 }
2987 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2988 {
2989 /*
2990 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2991 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2992 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2993 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2994 * mappings, see @bugref{6568}.
2995 *
2996 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2997 */
2998 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2999 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3000 HMVMX_SET_TAGGED_TLB_FLUSHED();
3001 }
3002 else if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3003 {
3004 /*
3005 * The nested-guest specifies its own guest-physical address to use as the APIC-access
3006 * address which requires flushing the TLB of EPT cached structures.
3007 *
3008 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
3009 */
3010 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
3011 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3012 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3013 HMVMX_SET_TAGGED_TLB_FLUSHED();
3014 }
3015
3016
3017 pVCpu->hm.s.fForceTLBFlush = false;
3018 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
3019
3020 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
3021 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
3022 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3023 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3024 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3025 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3026 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3027 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3028 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3029
3030 /* Update VMCS with the VPID. */
3031 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3032 AssertRC(rc);
3033
3034#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3035}
3036
3037
3038/**
3039 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3040 *
3041 * @param pHostCpu The HM physical-CPU structure.
3042 * @param pVCpu The cross context virtual CPU structure.
3043 * @param pVmcsInfo The VMCS info. object.
3044 *
3045 * @remarks Called with interrupts disabled.
3046 */
3047static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
3048{
3049 AssertPtr(pVCpu);
3050 AssertPtr(pHostCpu);
3051 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3052 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3053 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3054
3055 /*
3056 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3057 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3058 */
3059 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3060 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3061 {
3062 pVCpu->hm.s.fForceTLBFlush = true;
3063 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3064 }
3065
3066 /* Check for explicit TLB flushes. */
3067 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3068 {
3069 pVCpu->hm.s.fForceTLBFlush = true;
3070 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3071 }
3072
3073 /* Check for TLB flushes while switching to/from a nested-guest. */
3074 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3075 {
3076 pVCpu->hm.s.fForceTLBFlush = true;
3077 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3078 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3079 }
3080
3081 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3082 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3083
3084 if (pVCpu->hm.s.fForceTLBFlush)
3085 {
3086 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3087 pVCpu->hm.s.fForceTLBFlush = false;
3088 }
3089}
3090
3091
3092/**
3093 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3094 *
3095 * @param pHostCpu The HM physical-CPU structure.
3096 * @param pVCpu The cross context virtual CPU structure.
3097 *
3098 * @remarks Called with interrupts disabled.
3099 */
3100static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu)
3101{
3102 AssertPtr(pVCpu);
3103 AssertPtr(pHostCpu);
3104 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3105 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3106 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3107
3108 /*
3109 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3110 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3111 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3112 * cannot reuse the current ASID anymore.
3113 */
3114 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3115 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3116 {
3117 pVCpu->hm.s.fForceTLBFlush = true;
3118 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3119 }
3120
3121 /* Check for explicit TLB flushes. */
3122 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3123 {
3124 /*
3125 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3126 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3127 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3128 * include fExplicitFlush's too) - an obscure corner case.
3129 */
3130 pVCpu->hm.s.fForceTLBFlush = true;
3131 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3132 }
3133
3134 /* Check for TLB flushes while switching to/from a nested-guest. */
3135 if (pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb)
3136 {
3137 pVCpu->hm.s.fForceTLBFlush = true;
3138 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = false;
3139 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbNstGst);
3140 }
3141
3142 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3143 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3144 if (pVCpu->hm.s.fForceTLBFlush)
3145 {
3146 ++pHostCpu->uCurrentAsid;
3147 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3148 {
3149 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3150 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3151 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3152 }
3153
3154 pVCpu->hm.s.fForceTLBFlush = false;
3155 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3156 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3157 if (pHostCpu->fFlushAsidBeforeUse)
3158 {
3159 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3160 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3161 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3162 {
3163 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3164 pHostCpu->fFlushAsidBeforeUse = false;
3165 }
3166 else
3167 {
3168 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3169 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3170 }
3171 }
3172 }
3173
3174 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3175 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3176 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3177 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3178 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3179 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3180 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3181
3182 int rc = VMXWriteVmcs16(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3183 AssertRC(rc);
3184}
3185
3186
3187/**
3188 * Flushes the guest TLB entry based on CPU capabilities.
3189 *
3190 * @param pHostCpu The HM physical-CPU structure.
3191 * @param pVCpu The cross context virtual CPU structure.
3192 * @param pVmcsInfo The VMCS info. object.
3193 *
3194 * @remarks Called with interrupts disabled.
3195 */
3196static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3197{
3198#ifdef HMVMX_ALWAYS_FLUSH_TLB
3199 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3200#endif
3201 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3202 switch (pVM->hm.s.vmx.enmTlbFlushType)
3203 {
3204 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3205 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3206 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3207 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3208 default:
3209 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3210 break;
3211 }
3212 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3213}
3214
3215
3216/**
3217 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3218 * TLB entries from the host TLB before VM-entry.
3219 *
3220 * @returns VBox status code.
3221 * @param pVM The cross context VM structure.
3222 */
3223static int hmR0VmxSetupTaggedTlb(PVMCC pVM)
3224{
3225 /*
3226 * Determine optimal flush type for nested paging.
3227 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3228 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3229 */
3230 if (pVM->hm.s.fNestedPaging)
3231 {
3232 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3233 {
3234 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3235 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3236 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3237 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3238 else
3239 {
3240 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3241 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3242 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3243 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3244 }
3245
3246 /* Make sure the write-back cacheable memory type for EPT is supported. */
3247 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3248 {
3249 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3250 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3251 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3252 }
3253
3254 /* EPT requires a page-walk length of 4. */
3255 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3256 {
3257 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3258 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3259 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3260 }
3261 }
3262 else
3263 {
3264 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3265 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3266 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3267 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3268 }
3269 }
3270
3271 /*
3272 * Determine optimal flush type for VPID.
3273 */
3274 if (pVM->hm.s.vmx.fVpid)
3275 {
3276 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3277 {
3278 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3279 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3280 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3281 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3282 else
3283 {
3284 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3285 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3286 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3287 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3288 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3289 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3290 pVM->hm.s.vmx.fVpid = false;
3291 }
3292 }
3293 else
3294 {
3295 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3296 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3297 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3298 pVM->hm.s.vmx.fVpid = false;
3299 }
3300 }
3301
3302 /*
3303 * Setup the handler for flushing tagged-TLBs.
3304 */
3305 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3306 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3307 else if (pVM->hm.s.fNestedPaging)
3308 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3309 else if (pVM->hm.s.vmx.fVpid)
3310 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3311 else
3312 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3313 return VINF_SUCCESS;
3314}
3315
3316
3317#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3318/**
3319 * Sets up the shadow VMCS fields arrays.
3320 *
3321 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3322 * executing the guest.
3323 *
3324 * @returns VBox status code.
3325 * @param pVM The cross context VM structure.
3326 */
3327static int hmR0VmxSetupShadowVmcsFieldsArrays(PVMCC pVM)
3328{
3329 /*
3330 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3331 * when the host does not support it.
3332 */
3333 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3334 if ( !fGstVmwriteAll
3335 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3336 { /* likely. */ }
3337 else
3338 {
3339 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3340 VMCC_GET_CPU_0(pVM)->hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3341 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3342 }
3343
3344 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3345 uint32_t cRwFields = 0;
3346 uint32_t cRoFields = 0;
3347 for (uint32_t i = 0; i < cVmcsFields; i++)
3348 {
3349 VMXVMCSFIELD VmcsField;
3350 VmcsField.u = g_aVmcsFields[i];
3351
3352 /*
3353 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3354 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3355 * in the shadow VMCS fields array as they would be redundant.
3356 *
3357 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3358 * we must not include it in the shadow VMCS fields array. Guests attempting to
3359 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3360 * the required behavior.
3361 */
3362 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3363 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3364 {
3365 /*
3366 * Read-only fields are placed in a separate array so that while syncing shadow
3367 * VMCS fields later (which is more performance critical) we can avoid branches.
3368 *
3369 * However, if the guest can write to all fields (including read-only fields),
3370 * we treat it a as read/write field. Otherwise, writing to these fields would
3371 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3372 */
3373 if ( fGstVmwriteAll
3374 || !VMXIsVmcsFieldReadOnly(VmcsField.u))
3375 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3376 else
3377 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3378 }
3379 }
3380
3381 /* Update the counts. */
3382 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3383 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3384 return VINF_SUCCESS;
3385}
3386
3387
3388/**
3389 * Sets up the VMREAD and VMWRITE bitmaps.
3390 *
3391 * @param pVM The cross context VM structure.
3392 */
3393static void hmR0VmxSetupVmreadVmwriteBitmaps(PVMCC pVM)
3394{
3395 /*
3396 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3397 */
3398 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3399 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3400 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3401 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3402 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3403
3404 /*
3405 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3406 * VMREAD and VMWRITE bitmaps.
3407 */
3408 {
3409 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3410 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3411 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3412 {
3413 uint32_t const uVmcsField = paShadowVmcsFields[i];
3414 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3415 Assert(uVmcsField >> 3 < cbBitmap);
3416 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3417 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3418 }
3419 }
3420
3421 /*
3422 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3423 * if the host supports VMWRITE to all supported VMCS fields.
3424 */
3425 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3426 {
3427 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3428 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3429 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3430 {
3431 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3432 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3433 Assert(uVmcsField >> 3 < cbBitmap);
3434 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3435 }
3436 }
3437}
3438#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3439
3440
3441/**
3442 * Sets up the virtual-APIC page address for the VMCS.
3443 *
3444 * @param pVmcsInfo The VMCS info. object.
3445 */
3446DECLINLINE(void) hmR0VmxSetupVmcsVirtApicAddr(PCVMXVMCSINFO pVmcsInfo)
3447{
3448 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3449 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3450 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3451 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3452 AssertRC(rc);
3453}
3454
3455
3456/**
3457 * Sets up the MSR-bitmap address for the VMCS.
3458 *
3459 * @param pVmcsInfo The VMCS info. object.
3460 */
3461DECLINLINE(void) hmR0VmxSetupVmcsMsrBitmapAddr(PCVMXVMCSINFO pVmcsInfo)
3462{
3463 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3464 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3465 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3466 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3467 AssertRC(rc);
3468}
3469
3470
3471/**
3472 * Sets up the APIC-access page address for the VMCS.
3473 *
3474 * @param pVCpu The cross context virtual CPU structure.
3475 */
3476DECLINLINE(void) hmR0VmxSetupVmcsApicAccessAddr(PVMCPUCC pVCpu)
3477{
3478 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3479 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3480 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3481 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3482 AssertRC(rc);
3483}
3484
3485
3486#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3487/**
3488 * Sets up the VMREAD bitmap address for the VMCS.
3489 *
3490 * @param pVCpu The cross context virtual CPU structure.
3491 */
3492DECLINLINE(void) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPUCC pVCpu)
3493{
3494 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3495 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3496 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3497 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3498 AssertRC(rc);
3499}
3500
3501
3502/**
3503 * Sets up the VMWRITE bitmap address for the VMCS.
3504 *
3505 * @param pVCpu The cross context virtual CPU structure.
3506 */
3507DECLINLINE(void) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPUCC pVCpu)
3508{
3509 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3510 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3511 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3512 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3513 AssertRC(rc);
3514}
3515#endif
3516
3517
3518/**
3519 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3520 * in the VMCS.
3521 *
3522 * @returns VBox status code.
3523 * @param pVmcsInfo The VMCS info. object.
3524 */
3525DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMXVMCSINFO pVmcsInfo)
3526{
3527 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3528 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3529 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3530
3531 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3532 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3533 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3534
3535 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3536 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3537 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3538
3539 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad); AssertRC(rc);
3540 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore); AssertRC(rc);
3541 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad); AssertRC(rc);
3542 return VINF_SUCCESS;
3543}
3544
3545
3546/**
3547 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3548 *
3549 * @param pVCpu The cross context virtual CPU structure.
3550 * @param pVmcsInfo The VMCS info. object.
3551 */
3552static void hmR0VmxSetupVmcsMsrPermissions(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3553{
3554 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3555
3556 /*
3557 * The guest can access the following MSRs (read, write) without causing
3558 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3559 */
3560 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3561 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3562 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3563 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3564 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3565 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3566
3567 /*
3568 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3569 * associated with then. We never need to intercept access (writes need to be
3570 * executed without causing a VM-exit, reads will #GP fault anyway).
3571 *
3572 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3573 * read/write them. We swap the the guest/host MSR value using the
3574 * auto-load/store MSR area.
3575 */
3576 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3577 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3578 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3579 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3580 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3581 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3582
3583 /*
3584 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3585 * required for 64-bit guests.
3586 */
3587 if (pVM->hm.s.fAllow64BitGuests)
3588 {
3589 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3590 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3591 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3592 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3593 }
3594
3595 /*
3596 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3597 */
3598#ifdef VBOX_STRICT
3599 Assert(pVmcsInfo->pvMsrBitmap);
3600 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3601 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3602#endif
3603}
3604
3605
3606/**
3607 * Sets up pin-based VM-execution controls in the VMCS.
3608 *
3609 * @returns VBox status code.
3610 * @param pVCpu The cross context virtual CPU structure.
3611 * @param pVmcsInfo The VMCS info. object.
3612 */
3613static int hmR0VmxSetupVmcsPinCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3614{
3615 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3616 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3617 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3618
3619 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3620 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3621
3622 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3623 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3624
3625 /* Enable the VMX-preemption timer. */
3626 if (pVM->hm.s.vmx.fUsePreemptTimer)
3627 {
3628 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3629 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3630 }
3631
3632#if 0
3633 /* Enable posted-interrupt processing. */
3634 if (pVM->hm.s.fPostedIntrs)
3635 {
3636 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3637 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3638 fVal |= VMX_PIN_CTLS_POSTED_INT;
3639 }
3640#endif
3641
3642 if ((fVal & fZap) != fVal)
3643 {
3644 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3645 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3646 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3647 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3648 }
3649
3650 /* Commit it to the VMCS and update our cache. */
3651 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3652 AssertRC(rc);
3653 pVmcsInfo->u32PinCtls = fVal;
3654
3655 return VINF_SUCCESS;
3656}
3657
3658
3659/**
3660 * Sets up secondary processor-based VM-execution controls in the VMCS.
3661 *
3662 * @returns VBox status code.
3663 * @param pVCpu The cross context virtual CPU structure.
3664 * @param pVmcsInfo The VMCS info. object.
3665 */
3666static int hmR0VmxSetupVmcsProcCtls2(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3667{
3668 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3669 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3670 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3671
3672 /* WBINVD causes a VM-exit. */
3673 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3674 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3675
3676 /* Enable EPT (aka nested-paging). */
3677 if (pVM->hm.s.fNestedPaging)
3678 fVal |= VMX_PROC_CTLS2_EPT;
3679
3680 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3681 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3682 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3683 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3684 fVal |= VMX_PROC_CTLS2_INVPCID;
3685
3686 /* Enable VPID. */
3687 if (pVM->hm.s.vmx.fVpid)
3688 fVal |= VMX_PROC_CTLS2_VPID;
3689
3690 /* Enable unrestricted guest execution. */
3691 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3692 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3693
3694#if 0
3695 if (pVM->hm.s.fVirtApicRegs)
3696 {
3697 /* Enable APIC-register virtualization. */
3698 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3699 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3700
3701 /* Enable virtual-interrupt delivery. */
3702 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3703 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3704 }
3705#endif
3706
3707 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3708 where the TPR shadow resides. */
3709 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3710 * done dynamically. */
3711 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3712 {
3713 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3714 hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3715 }
3716
3717 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3718 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3719 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3720 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3721 fVal |= VMX_PROC_CTLS2_RDTSCP;
3722
3723 /* Enable Pause-Loop exiting. */
3724 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3725 && pVM->hm.s.vmx.cPleGapTicks
3726 && pVM->hm.s.vmx.cPleWindowTicks)
3727 {
3728 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3729
3730 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks); AssertRC(rc);
3731 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks); AssertRC(rc);
3732 }
3733
3734 if ((fVal & fZap) != fVal)
3735 {
3736 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3737 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3738 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3739 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3740 }
3741
3742 /* Commit it to the VMCS and update our cache. */
3743 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3744 AssertRC(rc);
3745 pVmcsInfo->u32ProcCtls2 = fVal;
3746
3747 return VINF_SUCCESS;
3748}
3749
3750
3751/**
3752 * Sets up processor-based VM-execution controls in the VMCS.
3753 *
3754 * @returns VBox status code.
3755 * @param pVCpu The cross context virtual CPU structure.
3756 * @param pVmcsInfo The VMCS info. object.
3757 */
3758static int hmR0VmxSetupVmcsProcCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3759{
3760 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3761
3762 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3763 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3764
3765 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3766 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3767 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3768 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3769 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3770 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3771 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3772
3773 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3774 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3775 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3776 {
3777 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3778 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3779 }
3780
3781 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3782 if (!pVM->hm.s.fNestedPaging)
3783 {
3784 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3785 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3786 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3787 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3788 }
3789
3790 /* Use TPR shadowing if supported by the CPU. */
3791 if ( PDMHasApic(pVM)
3792 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3793 {
3794 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3795 /* CR8 writes cause a VM-exit based on TPR threshold. */
3796 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3797 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3798 hmR0VmxSetupVmcsVirtApicAddr(pVmcsInfo);
3799 }
3800 else
3801 {
3802 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3803 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3804 if (pVM->hm.s.fAllow64BitGuests)
3805 {
3806 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3807 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3808 }
3809 }
3810
3811 /* Use MSR-bitmaps if supported by the CPU. */
3812 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3813 {
3814 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3815 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3816 }
3817
3818 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3819 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3820 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3821
3822 if ((fVal & fZap) != fVal)
3823 {
3824 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3825 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3826 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3827 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3828 }
3829
3830 /* Commit it to the VMCS and update our cache. */
3831 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3832 AssertRC(rc);
3833 pVmcsInfo->u32ProcCtls = fVal;
3834
3835 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3836 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3837 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3838
3839 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3840 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3841 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3842
3843 /* Sanity check, should not really happen. */
3844 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3845 { /* likely */ }
3846 else
3847 {
3848 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3849 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3850 }
3851
3852 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3853 return VINF_SUCCESS;
3854}
3855
3856
3857/**
3858 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3859 * Processor-based VM-execution) control fields in the VMCS.
3860 *
3861 * @returns VBox status code.
3862 * @param pVCpu The cross context virtual CPU structure.
3863 * @param pVmcsInfo The VMCS info. object.
3864 */
3865static int hmR0VmxSetupVmcsMiscCtls(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3866{
3867#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3868 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3869 {
3870 hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3871 hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3872 }
3873#endif
3874
3875 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3876 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3877 AssertRC(rc);
3878
3879 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3880 if (RT_SUCCESS(rc))
3881 {
3882 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3883 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3884
3885 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask); AssertRC(rc);
3886 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask); AssertRC(rc);
3887
3888 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3889 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3890 return VINF_SUCCESS;
3891 }
3892 else
3893 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3894 return rc;
3895}
3896
3897
3898/**
3899 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3900 *
3901 * We shall setup those exception intercepts that don't change during the
3902 * lifetime of the VM here. The rest are done dynamically while loading the
3903 * guest state.
3904 *
3905 * @param pVCpu The cross context virtual CPU structure.
3906 * @param pVmcsInfo The VMCS info. object.
3907 */
3908static void hmR0VmxSetupVmcsXcptBitmap(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3909{
3910 /*
3911 * The following exceptions are always intercepted:
3912 *
3913 * #AC - To prevent the guest from hanging the CPU.
3914 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3915 * recursive #DBs can cause a CPU hang.
3916 * #PF - To sync our shadow page tables when nested-paging is not used.
3917 */
3918 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3919 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3920 | RT_BIT(X86_XCPT_DB)
3921 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3922
3923 /* Commit it to the VMCS. */
3924 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3925 AssertRC(rc);
3926
3927 /* Update our cache of the exception bitmap. */
3928 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3929}
3930
3931
3932#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3933/**
3934 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3935 *
3936 * @returns VBox status code.
3937 * @param pVCpu The cross context virtual CPU structure.
3938 * @param pVmcsInfo The VMCS info. object.
3939 */
3940static int hmR0VmxSetupVmcsCtlsNested(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
3941{
3942 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3943 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3944 AssertRC(rc);
3945
3946 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVmcsInfo);
3947 if (RT_SUCCESS(rc))
3948 {
3949 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3950 hmR0VmxSetupVmcsMsrBitmapAddr(pVmcsInfo);
3951
3952 /* Paranoia - We've not yet initialized these, they shall be done while merging the VMCS. */
3953 Assert(!pVmcsInfo->u64Cr0Mask);
3954 Assert(!pVmcsInfo->u64Cr4Mask);
3955 return VINF_SUCCESS;
3956 }
3957 else
3958 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3959 return rc;
3960}
3961#endif
3962
3963
3964/**
3965 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3966 * VMX.
3967 *
3968 * @returns VBox status code.
3969 * @param pVCpu The cross context virtual CPU structure.
3970 * @param pVmcsInfo The VMCS info. object.
3971 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3972 */
3973static int hmR0VmxSetupVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3974{
3975 Assert(pVmcsInfo->pvVmcs);
3976 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3977
3978 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3979 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
3980 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3981 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3982
3983 LogFlowFunc(("\n"));
3984
3985 /*
3986 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3987 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3988 */
3989 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3990 if (RT_SUCCESS(rc))
3991 {
3992 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3993 if (RT_SUCCESS(rc))
3994 {
3995 if (!fIsNstGstVmcs)
3996 {
3997 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3998 if (RT_SUCCESS(rc))
3999 {
4000 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
4001 if (RT_SUCCESS(rc))
4002 {
4003 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
4004 if (RT_SUCCESS(rc))
4005 {
4006 hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4007#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4008 /*
4009 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4010 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4011 * making it fit for use when VMCS shadowing is later enabled.
4012 */
4013 if (pVmcsInfo->pvShadowVmcs)
4014 {
4015 VMXVMCSREVID VmcsRevId;
4016 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4017 VmcsRevId.n.fIsShadowVmcs = 1;
4018 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4019 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4020 if (RT_SUCCESS(rc))
4021 { /* likely */ }
4022 else
4023 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4024 }
4025#endif
4026 }
4027 else
4028 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4029 }
4030 else
4031 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4032 }
4033 else
4034 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4035 }
4036 else
4037 {
4038#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4039 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4040 if (RT_SUCCESS(rc))
4041 { /* likely */ }
4042 else
4043 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4044#else
4045 AssertFailed();
4046#endif
4047 }
4048 }
4049 else
4050 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4051 }
4052 else
4053 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4054
4055 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4056 if (RT_SUCCESS(rc))
4057 {
4058 rc = hmR0VmxClearVmcs(pVmcsInfo);
4059 if (RT_SUCCESS(rc))
4060 { /* likely */ }
4061 else
4062 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4063 }
4064
4065 /*
4066 * Update the last-error record both for failures and success, so we
4067 * can propagate the status code back to ring-3 for diagnostics.
4068 */
4069 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4070 NOREF(pszVmcs);
4071 return rc;
4072}
4073
4074
4075/**
4076 * Does global VT-x initialization (called during module initialization).
4077 *
4078 * @returns VBox status code.
4079 */
4080VMMR0DECL(int) VMXR0GlobalInit(void)
4081{
4082#ifdef HMVMX_USE_FUNCTION_TABLE
4083 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4084# ifdef VBOX_STRICT
4085 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4086 Assert(g_apfnVMExitHandlers[i]);
4087# endif
4088#endif
4089 return VINF_SUCCESS;
4090}
4091
4092
4093/**
4094 * Does global VT-x termination (called during module termination).
4095 */
4096VMMR0DECL(void) VMXR0GlobalTerm()
4097{
4098 /* Nothing to do currently. */
4099}
4100
4101
4102/**
4103 * Sets up and activates VT-x on the current CPU.
4104 *
4105 * @returns VBox status code.
4106 * @param pHostCpu The HM physical-CPU structure.
4107 * @param pVM The cross context VM structure. Can be
4108 * NULL after a host resume operation.
4109 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4110 * fEnabledByHost is @c true).
4111 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4112 * @a fEnabledByHost is @c true).
4113 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4114 * enable VT-x on the host.
4115 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4116 */
4117VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVMCC pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4118 PCSUPHWVIRTMSRS pHwvirtMsrs)
4119{
4120 AssertPtr(pHostCpu);
4121 AssertPtr(pHwvirtMsrs);
4122 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4123
4124 /* Enable VT-x if it's not already enabled by the host. */
4125 if (!fEnabledByHost)
4126 {
4127 int rc = hmR0VmxEnterRootMode(pHostCpu, pVM, HCPhysCpuPage, pvCpuPage);
4128 if (RT_FAILURE(rc))
4129 return rc;
4130 }
4131
4132 /*
4133 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4134 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4135 * invalidated when flushing by VPID.
4136 */
4137 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4138 {
4139 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4140 pHostCpu->fFlushAsidBeforeUse = false;
4141 }
4142 else
4143 pHostCpu->fFlushAsidBeforeUse = true;
4144
4145 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4146 ++pHostCpu->cTlbFlushes;
4147
4148 return VINF_SUCCESS;
4149}
4150
4151
4152/**
4153 * Deactivates VT-x on the current CPU.
4154 *
4155 * @returns VBox status code.
4156 * @param pHostCpu The HM physical-CPU structure.
4157 * @param pvCpuPage Pointer to the VMXON region.
4158 * @param HCPhysCpuPage Physical address of the VMXON region.
4159 *
4160 * @remarks This function should never be called when SUPR0EnableVTx() or
4161 * similar was used to enable VT-x on the host.
4162 */
4163VMMR0DECL(int) VMXR0DisableCpu(PHMPHYSCPU pHostCpu, void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4164{
4165 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4166
4167 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4168 return hmR0VmxLeaveRootMode(pHostCpu);
4169}
4170
4171
4172/**
4173 * Does per-VM VT-x initialization.
4174 *
4175 * @returns VBox status code.
4176 * @param pVM The cross context VM structure.
4177 */
4178VMMR0DECL(int) VMXR0InitVM(PVMCC pVM)
4179{
4180 AssertPtr(pVM);
4181 LogFlowFunc(("pVM=%p\n", pVM));
4182
4183 int rc = hmR0VmxStructsAlloc(pVM);
4184 if (RT_FAILURE(rc))
4185 {
4186 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4187 return rc;
4188 }
4189
4190 return VINF_SUCCESS;
4191}
4192
4193
4194/**
4195 * Does per-VM VT-x termination.
4196 *
4197 * @returns VBox status code.
4198 * @param pVM The cross context VM structure.
4199 */
4200VMMR0DECL(int) VMXR0TermVM(PVMCC pVM)
4201{
4202 AssertPtr(pVM);
4203 LogFlowFunc(("pVM=%p\n", pVM));
4204
4205#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4206 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4207 {
4208 Assert(pVM->hm.s.vmx.pvScratch);
4209 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4210 }
4211#endif
4212 hmR0VmxStructsFree(pVM);
4213 return VINF_SUCCESS;
4214}
4215
4216
4217/**
4218 * Sets up the VM for execution using hardware-assisted VMX.
4219 * This function is only called once per-VM during initialization.
4220 *
4221 * @returns VBox status code.
4222 * @param pVM The cross context VM structure.
4223 */
4224VMMR0DECL(int) VMXR0SetupVM(PVMCC pVM)
4225{
4226 AssertPtr(pVM);
4227 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4228
4229 LogFlowFunc(("pVM=%p\n", pVM));
4230
4231 /*
4232 * At least verify if VMX is enabled, since we can't check if we're in VMX root mode or not
4233 * without causing a #GP.
4234 */
4235 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4236 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4237 { /* likely */ }
4238 else
4239 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4240
4241 /*
4242 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4243 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4244 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4245 */
4246 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4247 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4248 || !pVM->hm.s.vmx.pRealModeTSS))
4249 {
4250 LogRelFunc(("Invalid real-on-v86 state.\n"));
4251 return VERR_INTERNAL_ERROR;
4252 }
4253
4254 /* Initialize these always, see hmR3InitFinalizeR0().*/
4255 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4256 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4257
4258 /* Setup the tagged-TLB flush handlers. */
4259 int rc = hmR0VmxSetupTaggedTlb(pVM);
4260 if (RT_FAILURE(rc))
4261 {
4262 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4263 return rc;
4264 }
4265
4266#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4267 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4268 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4269 {
4270 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4271 if (RT_SUCCESS(rc))
4272 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4273 else
4274 {
4275 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4276 return rc;
4277 }
4278 }
4279#endif
4280
4281 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4282 {
4283 PVMCPUCC pVCpu = VMCC_GET_CPU(pVM, idCpu);
4284 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4285
4286 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4287 if (RT_SUCCESS(rc))
4288 {
4289#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4290 if (pVM->cpum.ro.GuestFeatures.fVmx)
4291 {
4292 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4293 if (RT_SUCCESS(rc))
4294 { /* likely */ }
4295 else
4296 {
4297 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4298 return rc;
4299 }
4300 }
4301#endif
4302 }
4303 else
4304 {
4305 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4306 return rc;
4307 }
4308 }
4309
4310 return VINF_SUCCESS;
4311}
4312
4313
4314/**
4315 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4316 * the VMCS.
4317 */
4318static void hmR0VmxExportHostControlRegs(void)
4319{
4320 int rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR0, ASMGetCR0()); AssertRC(rc);
4321 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR3, ASMGetCR3()); AssertRC(rc);
4322 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_CR4, ASMGetCR4()); AssertRC(rc);
4323}
4324
4325
4326/**
4327 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4328 * the host-state area in the VMCS.
4329 *
4330 * @returns VBox status code.
4331 * @param pVCpu The cross context virtual CPU structure.
4332 */
4333static int hmR0VmxExportHostSegmentRegs(PVMCPUCC pVCpu)
4334{
4335/**
4336 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4337 * requirements. See hmR0VmxExportHostSegmentRegs().
4338 */
4339#define VMXLOCAL_ADJUST_HOST_SEG(a_Seg, a_selValue) \
4340 if ((a_selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4341 { \
4342 bool fValidSelector = true; \
4343 if ((a_selValue) & X86_SEL_LDT) \
4344 { \
4345 uint32_t const uAttr = ASMGetSegAttr(a_selValue); \
4346 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4347 } \
4348 if (fValidSelector) \
4349 { \
4350 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##a_Seg; \
4351 pVCpu->hm.s.vmx.RestoreHost.uHostSel##a_Seg = (a_selValue); \
4352 } \
4353 (a_selValue) = 0; \
4354 }
4355
4356 /*
4357 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4358 * will be messed up. We should -not- save the messed up state without restoring
4359 * the original host-state, see @bugref{7240}.
4360 *
4361 * This apparently can happen (most likely the FPU changes), deal with it rather than
4362 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4363 */
4364 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4365 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4366 {
4367 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4368 pVCpu->idCpu));
4369 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4370 }
4371 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4372
4373 /*
4374 * Host segment registers.
4375 */
4376 RTSEL uSelES = ASMGetES();
4377 RTSEL uSelCS = ASMGetCS();
4378 RTSEL uSelSS = ASMGetSS();
4379 RTSEL uSelDS = ASMGetDS();
4380 RTSEL uSelFS = ASMGetFS();
4381 RTSEL uSelGS = ASMGetGS();
4382 RTSEL uSelTR = ASMGetTR();
4383
4384 /*
4385 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4386 * gain VM-entry and restore them before we get preempted.
4387 *
4388 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4389 */
4390 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4391 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4392 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4393 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4394
4395 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4396 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4397 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4398 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4399 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4400 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4401 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4402 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4403 Assert(uSelCS);
4404 Assert(uSelTR);
4405
4406 /* Write these host selector fields into the host-state area in the VMCS. */
4407 int rc = VMXWriteVmcs16(VMX_VMCS16_HOST_CS_SEL, uSelCS); AssertRC(rc);
4408 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_SS_SEL, uSelSS); AssertRC(rc);
4409 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_DS_SEL, uSelDS); AssertRC(rc);
4410 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_ES_SEL, uSelES); AssertRC(rc);
4411 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_FS_SEL, uSelFS); AssertRC(rc);
4412 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_GS_SEL, uSelGS); AssertRC(rc);
4413 rc = VMXWriteVmcs16(VMX_VMCS16_HOST_TR_SEL, uSelTR); AssertRC(rc);
4414
4415 /*
4416 * Host GDTR and IDTR.
4417 */
4418 RTGDTR Gdtr;
4419 RTIDTR Idtr;
4420 RT_ZERO(Gdtr);
4421 RT_ZERO(Idtr);
4422 ASMGetGDTR(&Gdtr);
4423 ASMGetIDTR(&Idtr);
4424 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt); AssertRC(rc);
4425 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt); AssertRC(rc);
4426
4427 /*
4428 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4429 * them to the maximum limit (0xffff) on every VM-exit.
4430 */
4431 if (Gdtr.cbGdt != 0xffff)
4432 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4433
4434 /*
4435 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4436 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4437 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4438 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4439 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4440 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4441 * at 0xffff on hosts where we are sure it won't cause trouble.
4442 */
4443#if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4444 if (Idtr.cbIdt < 0x0fff)
4445#else
4446 if (Idtr.cbIdt != 0xffff)
4447#endif
4448 {
4449 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4450 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4451 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4452 }
4453
4454 /*
4455 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4456 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4457 * RPL should be too in most cases.
4458 */
4459 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4460 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4461
4462 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4463 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4464
4465 /*
4466 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4467 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4468 * restoration if the host has something else. Task switching is not supported in 64-bit
4469 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4470 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4471 *
4472 * [1] See Intel spec. 3.5 "System Descriptor Types".
4473 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4474 */
4475 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4476 Assert(pDesc->System.u4Type == 11);
4477 if ( pDesc->System.u16LimitLow != 0x67
4478 || pDesc->System.u4LimitHigh)
4479 {
4480 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4481 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4482 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4483 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4484 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4485 }
4486
4487 /*
4488 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4489 */
4490 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4491 {
4492 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4493 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4494 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4495 {
4496 /* The GDT is read-only but the writable GDT is available. */
4497 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4498 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4499 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4500 AssertRCReturn(rc, rc);
4501 }
4502 }
4503
4504 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_TR_BASE, uTRBase);
4505 AssertRC(rc);
4506
4507 /*
4508 * Host FS base and GS base.
4509 */
4510 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4511 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4512 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_FS_BASE, u64FSBase); AssertRC(rc);
4513 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_GS_BASE, u64GSBase); AssertRC(rc);
4514
4515 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4516 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4517 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4518 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4519 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4520
4521 return VINF_SUCCESS;
4522#undef VMXLOCAL_ADJUST_HOST_SEG
4523}
4524
4525
4526/**
4527 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4528 * host-state area of the VMCS.
4529 *
4530 * These MSRs will be automatically restored on the host after every successful
4531 * VM-exit.
4532 *
4533 * @param pVCpu The cross context virtual CPU structure.
4534 *
4535 * @remarks No-long-jump zone!!!
4536 */
4537static void hmR0VmxExportHostMsrs(PVMCPUCC pVCpu)
4538{
4539 AssertPtr(pVCpu);
4540
4541 /*
4542 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4543 * rather than swapping them on every VM-entry.
4544 */
4545 hmR0VmxLazySaveHostMsrs(pVCpu);
4546
4547 /*
4548 * Host Sysenter MSRs.
4549 */
4550 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS)); AssertRC(rc);
4551 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP)); AssertRC(rc);
4552 rc = VMXWriteVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP)); AssertRC(rc);
4553
4554 /*
4555 * Host EFER MSR.
4556 *
4557 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4558 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4559 */
4560 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4561 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4562 {
4563 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4564 AssertRC(rc);
4565 }
4566
4567 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4568 * hmR0VmxExportGuestEntryExitCtls(). */
4569}
4570
4571
4572/**
4573 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4574 *
4575 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4576 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4577 *
4578 * @returns true if we need to load guest EFER, false otherwise.
4579 * @param pVCpu The cross context virtual CPU structure.
4580 * @param pVmxTransient The VMX-transient structure.
4581 *
4582 * @remarks Requires EFER, CR4.
4583 * @remarks No-long-jump zone!!!
4584 */
4585static bool hmR0VmxShouldSwapEferMsr(PCVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4586{
4587#ifdef HMVMX_ALWAYS_SWAP_EFER
4588 RT_NOREF2(pVCpu, pVmxTransient);
4589 return true;
4590#else
4591 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4592 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4593 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4594 uint64_t const u64GuestEfer = pCtx->msrEFER;
4595
4596# ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4597 /*
4598 * For nested-guests, we shall honor swapping the EFER MSR when requested by
4599 * the nested-guest.
4600 */
4601 if ( pVmxTransient->fIsNestedGuest
4602 && ( CPUMIsGuestVmxEntryCtlsSet(pVCpu, pCtx, VMX_ENTRY_CTLS_LOAD_EFER_MSR)
4603 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_SAVE_EFER_MSR)
4604 || CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_LOAD_EFER_MSR)))
4605 return true;
4606# else
4607 RT_NOREF(pVmxTransient);
4608#endif
4609
4610 /*
4611 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4612 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4613 */
4614 if ( CPUMIsGuestInLongModeEx(pCtx)
4615 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4616 return true;
4617
4618 /*
4619 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4620 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4621 *
4622 * See Intel spec. 4.5 "IA-32e Paging".
4623 * See Intel spec. 4.1.1 "Three Paging Modes".
4624 *
4625 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4626 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4627 */
4628 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4629 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4630 if ( (pCtx->cr4 & X86_CR4_PAE)
4631 && (pCtx->cr0 & X86_CR0_PG))
4632 {
4633 /*
4634 * If nested paging is not used, verify that the guest paging mode matches the
4635 * shadow paging mode which is/will be placed in the VMCS (which is what will
4636 * actually be used while executing the guest and not the CR4 shadow value).
4637 */
4638 AssertMsg(pVM->hm.s.fNestedPaging || ( pVCpu->hm.s.enmShadowMode == PGMMODE_PAE
4639 || pVCpu->hm.s.enmShadowMode == PGMMODE_PAE_NX
4640 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64
4641 || pVCpu->hm.s.enmShadowMode == PGMMODE_AMD64_NX),
4642 ("enmShadowMode=%u\n", pVCpu->hm.s.enmShadowMode));
4643 if ((u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4644 {
4645 /* Verify that the host is NX capable. */
4646 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4647 return true;
4648 }
4649 }
4650
4651 return false;
4652#endif
4653}
4654
4655
4656/**
4657 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4658 * VMCS.
4659 *
4660 * This is typically required when the guest changes paging mode.
4661 *
4662 * @returns VBox status code.
4663 * @param pVCpu The cross context virtual CPU structure.
4664 * @param pVmxTransient The VMX-transient structure.
4665 *
4666 * @remarks Requires EFER.
4667 * @remarks No-long-jump zone!!!
4668 */
4669static int hmR0VmxExportGuestEntryExitCtls(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4670{
4671 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4672 {
4673 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
4674 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4675 bool const fGstInLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
4676
4677 /*
4678 * VMRUN function.
4679 * If the guest is in long mode, use the 64-bit guest handler, else the 32-bit guest handler.
4680 * The host is always 64-bit since we no longer support 32-bit hosts.
4681 */
4682 if (fGstInLongMode)
4683 {
4684#ifndef VBOX_WITH_64_BITS_GUESTS
4685 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
4686#else
4687 Assert(pVM->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
4688 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
4689#endif
4690 }
4691 else
4692 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
4693
4694 /*
4695 * VM-entry controls.
4696 */
4697 {
4698 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4699 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4700
4701 /*
4702 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4703 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4704 *
4705 * For nested-guests, this is a mandatory VM-entry control. It's also
4706 * required because we do not want to leak host bits to the nested-guest.
4707 */
4708 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4709
4710 /*
4711 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4712 *
4713 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4714 * required to get the nested-guest working with hardware-assisted VMX execution.
4715 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a nested hypervisor
4716 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4717 * here rather than while merging the guest VMCS controls.
4718 */
4719 if (fGstInLongMode)
4720 {
4721 Assert(pVCpu->cpum.GstCtx.msrEFER & MSR_K6_EFER_LME);
4722 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4723 }
4724 else
4725 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4726
4727 /*
4728 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4729 *
4730 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4731 * regardless of whether the nested-guest VMCS specifies it because we are free to
4732 * load whatever MSRs we require and we do not need to modify the guest visible copy
4733 * of the VM-entry MSR load area.
4734 */
4735 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4736 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4737 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4738 else
4739 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4740
4741 /*
4742 * The following should -not- be set (since we're not in SMM mode):
4743 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4744 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4745 */
4746
4747 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4748 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4749
4750 if ((fVal & fZap) == fVal)
4751 { /* likely */ }
4752 else
4753 {
4754 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
4755 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
4756 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
4757 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4758 }
4759
4760 /* Commit it to the VMCS. */
4761 if (pVmcsInfo->u32EntryCtls != fVal)
4762 {
4763 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
4764 AssertRC(rc);
4765 pVmcsInfo->u32EntryCtls = fVal;
4766 }
4767 }
4768
4769 /*
4770 * VM-exit controls.
4771 */
4772 {
4773 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4774 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4775
4776 /*
4777 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
4778 * supported the 1-setting of this bit.
4779 *
4780 * For nested-guests, we set the "save debug controls" as the converse
4781 * "load debug controls" is mandatory for nested-guests anyway.
4782 */
4783 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
4784
4785 /*
4786 * Set the host long mode active (EFER.LMA) bit (which Intel calls
4787 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
4788 * host EFER.LMA and EFER.LME bit to this value. See assertion in
4789 * hmR0VmxExportHostMsrs().
4790 *
4791 * For nested-guests, we always set this bit as we do not support 32-bit
4792 * hosts.
4793 */
4794 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
4795
4796 /*
4797 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
4798 *
4799 * For nested-guests, we should use the "save IA32_EFER" control if we also
4800 * used the "load IA32_EFER" control while exporting VM-entry controls.
4801 */
4802 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4803 && hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
4804 {
4805 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
4806 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
4807 }
4808
4809 /*
4810 * Enable saving of the VMX-preemption timer value on VM-exit.
4811 * For nested-guests, currently not exposed/used.
4812 */
4813 if ( pVM->hm.s.vmx.fUsePreemptTimer
4814 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
4815 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
4816
4817 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
4818 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
4819
4820 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
4821 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
4822 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
4823
4824 if ((fVal & fZap) == fVal)
4825 { /* likely */ }
4826 else
4827 {
4828 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
4829 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
4830 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
4831 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
4832 }
4833
4834 /* Commit it to the VMCS. */
4835 if (pVmcsInfo->u32ExitCtls != fVal)
4836 {
4837 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
4838 AssertRC(rc);
4839 pVmcsInfo->u32ExitCtls = fVal;
4840 }
4841 }
4842
4843 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
4844 }
4845 return VINF_SUCCESS;
4846}
4847
4848
4849/**
4850 * Sets the TPR threshold in the VMCS.
4851 *
4852 * @param pVmcsInfo The VMCS info. object.
4853 * @param u32TprThreshold The TPR threshold (task-priority class only).
4854 */
4855DECLINLINE(void) hmR0VmxApicSetTprThreshold(PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
4856{
4857 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
4858 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
4859 RT_NOREF(pVmcsInfo);
4860 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
4861 AssertRC(rc);
4862}
4863
4864
4865/**
4866 * Exports the guest APIC TPR state into the VMCS.
4867 *
4868 * @param pVCpu The cross context virtual CPU structure.
4869 * @param pVmxTransient The VMX-transient structure.
4870 *
4871 * @remarks No-long-jump zone!!!
4872 */
4873static void hmR0VmxExportGuestApicTpr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4874{
4875 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
4876 {
4877 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
4878
4879 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4880 if (!pVmxTransient->fIsNestedGuest)
4881 {
4882 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
4883 && APICIsEnabled(pVCpu))
4884 {
4885 /*
4886 * Setup TPR shadowing.
4887 */
4888 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
4889 {
4890 bool fPendingIntr = false;
4891 uint8_t u8Tpr = 0;
4892 uint8_t u8PendingIntr = 0;
4893 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
4894 AssertRC(rc);
4895
4896 /*
4897 * If there are interrupts pending but masked by the TPR, instruct VT-x to
4898 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
4899 * priority of the pending interrupt so we can deliver the interrupt. If there
4900 * are no interrupts pending, set threshold to 0 to not cause any
4901 * TPR-below-threshold VM-exits.
4902 */
4903 uint32_t u32TprThreshold = 0;
4904 if (fPendingIntr)
4905 {
4906 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
4907 (which is the Task-Priority Class). */
4908 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
4909 const uint8_t u8TprPriority = u8Tpr >> 4;
4910 if (u8PendingPriority <= u8TprPriority)
4911 u32TprThreshold = u8PendingPriority;
4912 }
4913
4914 hmR0VmxApicSetTprThreshold(pVmcsInfo, u32TprThreshold);
4915 }
4916 }
4917 }
4918 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
4919 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
4920 }
4921}
4922
4923
4924/**
4925 * Gets the guest interruptibility-state.
4926 *
4927 * @returns Guest's interruptibility-state.
4928 * @param pVCpu The cross context virtual CPU structure.
4929 * @param pVmxTransient The VMX-transient structure.
4930 *
4931 * @remarks No-long-jump zone!!!
4932 */
4933static uint32_t hmR0VmxGetGuestIntrState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4934{
4935 /*
4936 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
4937 */
4938 uint32_t fIntrState = 0;
4939 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4940 {
4941 /* If inhibition is active, RIP and RFLAGS should've been imported from the VMCS already. */
4942 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
4943
4944 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4945 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
4946 {
4947 if (pCtx->eflags.Bits.u1IF)
4948 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
4949 else
4950 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
4951 }
4952 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
4953 {
4954 /*
4955 * We can clear the inhibit force flag as even if we go back to the recompiler
4956 * without executing guest code in VT-x, the flag's condition to be cleared is
4957 * met and thus the cleared state is correct.
4958 */
4959 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
4960 }
4961 }
4962
4963 /*
4964 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
4965 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
4966 * setting this would block host-NMIs and IRET will not clear the blocking.
4967 *
4968 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
4969 *
4970 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
4971 */
4972 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4973 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
4974 && CPUMIsGuestNmiBlocking(pVCpu))
4975 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
4976
4977 return fIntrState;
4978}
4979
4980
4981/**
4982 * Exports the exception intercepts required for guest execution in the VMCS.
4983 *
4984 * @param pVCpu The cross context virtual CPU structure.
4985 * @param pVmxTransient The VMX-transient structure.
4986 *
4987 * @remarks No-long-jump zone!!!
4988 */
4989static void hmR0VmxExportGuestXcptIntercepts(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
4990{
4991 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
4992 {
4993 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
4994 if ( !pVmxTransient->fIsNestedGuest
4995 && pVCpu->hm.s.fGIMTrapXcptUD)
4996 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
4997 else
4998 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
4999
5000 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5001 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5002 }
5003}
5004
5005
5006/**
5007 * Exports the guest's RIP into the guest-state area in the VMCS.
5008 *
5009 * @param pVCpu The cross context virtual CPU structure.
5010 *
5011 * @remarks No-long-jump zone!!!
5012 */
5013static void hmR0VmxExportGuestRip(PVMCPUCC pVCpu)
5014{
5015 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5016 {
5017 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5018
5019 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5020 AssertRC(rc);
5021
5022 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5023 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5024 }
5025}
5026
5027
5028/**
5029 * Exports the guest's RSP into the guest-state area in the VMCS.
5030 *
5031 * @param pVCpu The cross context virtual CPU structure.
5032 *
5033 * @remarks No-long-jump zone!!!
5034 */
5035static void hmR0VmxExportGuestRsp(PVMCPUCC pVCpu)
5036{
5037 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5038 {
5039 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5040
5041 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5042 AssertRC(rc);
5043
5044 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5045 Log4Func(("rsp=%#RX64\n", pVCpu->cpum.GstCtx.rsp));
5046 }
5047}
5048
5049
5050/**
5051 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5052 *
5053 * @param pVCpu The cross context virtual CPU structure.
5054 * @param pVmxTransient The VMX-transient structure.
5055 *
5056 * @remarks No-long-jump zone!!!
5057 */
5058static void hmR0VmxExportGuestRflags(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5059{
5060 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5061 {
5062 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5063
5064 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5065 Let us assert it as such and use 32-bit VMWRITE. */
5066 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5067 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5068 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5069 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5070
5071 /*
5072 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5073 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5074 * can run the real-mode guest code under Virtual 8086 mode.
5075 */
5076 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5077 if (pVmcsInfo->RealMode.fRealOnV86Active)
5078 {
5079 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5080 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5081 Assert(!pVmxTransient->fIsNestedGuest);
5082 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5083 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5084 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5085 }
5086
5087 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5088 AssertRC(rc);
5089
5090 /*
5091 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5092 *
5093 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5094 * through the hypervisor debugger using EFLAGS.TF.
5095 */
5096 if ( !pVmxTransient->fIsNestedGuest
5097 && !pVCpu->hm.s.fSingleInstruction
5098 && fEFlags.Bits.u1TF)
5099 {
5100 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5101 * premature trips to ring-3 esp since IEM does not yet handle it. */
5102 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5103 AssertRC(rc);
5104 }
5105 /* else: for nested-guest currently handling while merging controls. */
5106
5107 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5108 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5109 }
5110}
5111
5112
5113#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5114/**
5115 * Copies the nested-guest VMCS to the shadow VMCS.
5116 *
5117 * @returns VBox status code.
5118 * @param pVCpu The cross context virtual CPU structure.
5119 * @param pVmcsInfo The VMCS info. object.
5120 *
5121 * @remarks No-long-jump zone!!!
5122 */
5123static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5124{
5125 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5126 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5127
5128 /*
5129 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5130 * current VMCS, as we may try saving guest lazy MSRs.
5131 *
5132 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5133 * calling the import VMCS code which is currently performing the guest MSR reads
5134 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5135 * and the rest of the VMX leave session machinery.
5136 */
5137 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5138
5139 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5140 if (RT_SUCCESS(rc))
5141 {
5142 /*
5143 * Copy all guest read/write VMCS fields.
5144 *
5145 * We don't check for VMWRITE failures here for performance reasons and
5146 * because they are not expected to fail, barring irrecoverable conditions
5147 * like hardware errors.
5148 */
5149 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5150 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5151 {
5152 uint64_t u64Val;
5153 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5154 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5155 VMXWriteVmcs64(uVmcsField, u64Val);
5156 }
5157
5158 /*
5159 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5160 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5161 */
5162 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5163 {
5164 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5165 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5166 {
5167 uint64_t u64Val;
5168 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5169 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5170 VMXWriteVmcs64(uVmcsField, u64Val);
5171 }
5172 }
5173
5174 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5175 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5176 }
5177
5178 ASMSetFlags(fEFlags);
5179 return rc;
5180}
5181
5182
5183/**
5184 * Copies the shadow VMCS to the nested-guest VMCS.
5185 *
5186 * @returns VBox status code.
5187 * @param pVCpu The cross context virtual CPU structure.
5188 * @param pVmcsInfo The VMCS info. object.
5189 *
5190 * @remarks Called with interrupts disabled.
5191 */
5192static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5193{
5194 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5195 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5196 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5197
5198 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5199 if (RT_SUCCESS(rc))
5200 {
5201 /*
5202 * Copy guest read/write fields from the shadow VMCS.
5203 * Guest read-only fields cannot be modified, so no need to copy them.
5204 *
5205 * We don't check for VMREAD failures here for performance reasons and
5206 * because they are not expected to fail, barring irrecoverable conditions
5207 * like hardware errors.
5208 */
5209 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5210 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5211 {
5212 uint64_t u64Val;
5213 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5214 VMXReadVmcs64(uVmcsField, &u64Val);
5215 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5216 }
5217
5218 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5219 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5220 }
5221 return rc;
5222}
5223
5224
5225/**
5226 * Enables VMCS shadowing for the given VMCS info. object.
5227 *
5228 * @param pVmcsInfo The VMCS info. object.
5229 *
5230 * @remarks No-long-jump zone!!!
5231 */
5232static void hmR0VmxEnableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5233{
5234 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5235 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5236 {
5237 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5238 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5239 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5240 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs); AssertRC(rc);
5241 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5242 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5243 Log4Func(("Enabled\n"));
5244 }
5245}
5246
5247
5248/**
5249 * Disables VMCS shadowing for the given VMCS info. object.
5250 *
5251 * @param pVmcsInfo The VMCS info. object.
5252 *
5253 * @remarks No-long-jump zone!!!
5254 */
5255static void hmR0VmxDisableVmcsShadowing(PVMXVMCSINFO pVmcsInfo)
5256{
5257 /*
5258 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5259 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5260 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5261 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5262 *
5263 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5264 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5265 */
5266 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5267 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5268 {
5269 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5270 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2); AssertRC(rc);
5271 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS); AssertRC(rc);
5272 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5273 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5274 Log4Func(("Disabled\n"));
5275 }
5276}
5277#endif
5278
5279
5280/**
5281 * Exports the guest hardware-virtualization state.
5282 *
5283 * @returns VBox status code.
5284 * @param pVCpu The cross context virtual CPU structure.
5285 * @param pVmxTransient The VMX-transient structure.
5286 *
5287 * @remarks No-long-jump zone!!!
5288 */
5289static int hmR0VmxExportGuestHwvirtState(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5290{
5291 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5292 {
5293#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5294 /*
5295 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5296 * VMCS shadowing.
5297 */
5298 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5299 {
5300 /*
5301 * If the nested hypervisor has loaded a current VMCS and is in VMX root mode,
5302 * copy the nested hypervisor's current VMCS into the shadow VMCS and enable
5303 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5304 *
5305 * We check for VMX root mode here in case the guest executes VMXOFF without
5306 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5307 * not clear the current VMCS pointer.
5308 */
5309 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5310 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5311 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5312 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5313 {
5314 /* Paranoia. */
5315 Assert(!pVmxTransient->fIsNestedGuest);
5316
5317 /*
5318 * For performance reasons, also check if the nested hypervisor's current VMCS
5319 * was newly loaded or modified before copying it to the shadow VMCS.
5320 */
5321 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5322 {
5323 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5324 AssertRCReturn(rc, rc);
5325 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5326 }
5327 hmR0VmxEnableVmcsShadowing(pVmcsInfo);
5328 }
5329 else
5330 hmR0VmxDisableVmcsShadowing(pVmcsInfo);
5331 }
5332#else
5333 NOREF(pVmxTransient);
5334#endif
5335 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5336 }
5337 return VINF_SUCCESS;
5338}
5339
5340
5341/**
5342 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5343 *
5344 * The guest FPU state is always pre-loaded hence we don't need to bother about
5345 * sharing FPU related CR0 bits between the guest and host.
5346 *
5347 * @returns VBox status code.
5348 * @param pVCpu The cross context virtual CPU structure.
5349 * @param pVmxTransient The VMX-transient structure.
5350 *
5351 * @remarks No-long-jump zone!!!
5352 */
5353static int hmR0VmxExportGuestCR0(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5354{
5355 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5356 {
5357 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5358 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5359
5360 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0;
5361 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5362 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5363 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5364 else
5365 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5366
5367 if (!pVmxTransient->fIsNestedGuest)
5368 {
5369 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5370 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5371 uint64_t const u64ShadowCr0 = u64GuestCr0;
5372 Assert(!RT_HI_U32(u64GuestCr0));
5373
5374 /*
5375 * Setup VT-x's view of the guest CR0.
5376 */
5377 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5378 if (pVM->hm.s.fNestedPaging)
5379 {
5380 if (CPUMIsGuestPagingEnabled(pVCpu))
5381 {
5382 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5383 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5384 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5385 }
5386 else
5387 {
5388 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5389 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5390 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5391 }
5392
5393 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5394 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5395 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5396 }
5397 else
5398 {
5399 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5400 u64GuestCr0 |= X86_CR0_WP;
5401 }
5402
5403 /*
5404 * Guest FPU bits.
5405 *
5406 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5407 * using CR0.TS.
5408 *
5409 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5410 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5411 */
5412 u64GuestCr0 |= X86_CR0_NE;
5413
5414 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5415 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5416
5417 /*
5418 * Update exception intercepts.
5419 */
5420 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5421 if (pVmcsInfo->RealMode.fRealOnV86Active)
5422 {
5423 Assert(PDMVmmDevHeapIsEnabled(pVM));
5424 Assert(pVM->hm.s.vmx.pRealModeTSS);
5425 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5426 }
5427 else
5428 {
5429 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5430 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5431 if (fInterceptMF)
5432 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5433 }
5434
5435 /* Additional intercepts for debugging, define these yourself explicitly. */
5436#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5437 uXcptBitmap |= 0
5438 | RT_BIT(X86_XCPT_BP)
5439 | RT_BIT(X86_XCPT_DE)
5440 | RT_BIT(X86_XCPT_NM)
5441 | RT_BIT(X86_XCPT_TS)
5442 | RT_BIT(X86_XCPT_UD)
5443 | RT_BIT(X86_XCPT_NP)
5444 | RT_BIT(X86_XCPT_SS)
5445 | RT_BIT(X86_XCPT_GP)
5446 | RT_BIT(X86_XCPT_PF)
5447 | RT_BIT(X86_XCPT_MF)
5448 ;
5449#elif defined(HMVMX_ALWAYS_TRAP_PF)
5450 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5451#endif
5452 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5453 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5454 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5455
5456 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5457 u64GuestCr0 |= fSetCr0;
5458 u64GuestCr0 &= fZapCr0;
5459 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5460
5461 /* Commit the CR0 and related fields to the guest VMCS. */
5462 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5463 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5464 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5465 {
5466 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5467 AssertRC(rc);
5468 }
5469 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5470 {
5471 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5472 AssertRC(rc);
5473 }
5474
5475 /* Update our caches. */
5476 pVmcsInfo->u32ProcCtls = uProcCtls;
5477 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5478
5479 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5480 }
5481 else
5482 {
5483 /*
5484 * With nested-guests, we may have extended the guest/host mask here since we
5485 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5486 * (to read from the nested-guest CR0 read-shadow) than the nested hypervisor
5487 * originally supplied. We must copy those bits from the nested-guest CR0 into
5488 * the nested-guest CR0 read-shadow.
5489 */
5490 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5491 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5492 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5493 Assert(!RT_HI_U32(u64GuestCr0));
5494 Assert(u64GuestCr0 & X86_CR0_NE);
5495
5496 /* Apply the hardware specified CR0 fixed bits and enable caching. */
5497 u64GuestCr0 |= fSetCr0;
5498 u64GuestCr0 &= fZapCr0;
5499 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5500
5501 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5502 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR0, u64GuestCr0); AssertRC(rc);
5503 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0); AssertRC(rc);
5504
5505 Log4Func(("cr0=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5506 }
5507
5508 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5509 }
5510
5511 return VINF_SUCCESS;
5512}
5513
5514
5515/**
5516 * Exports the guest control registers (CR3, CR4) into the guest-state area
5517 * in the VMCS.
5518 *
5519 * @returns VBox strict status code.
5520 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5521 * without unrestricted guest access and the VMMDev is not presently
5522 * mapped (e.g. EFI32).
5523 *
5524 * @param pVCpu The cross context virtual CPU structure.
5525 * @param pVmxTransient The VMX-transient structure.
5526 *
5527 * @remarks No-long-jump zone!!!
5528 */
5529static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
5530{
5531 int rc = VINF_SUCCESS;
5532 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5533
5534 /*
5535 * Guest CR2.
5536 * It's always loaded in the assembler code. Nothing to do here.
5537 */
5538
5539 /*
5540 * Guest CR3.
5541 */
5542 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5543 {
5544 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5545
5546 if (pVM->hm.s.fNestedPaging)
5547 {
5548 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5549 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5550
5551 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5552 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5553 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5554 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5555
5556 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5557 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5558 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5559
5560 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5561 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5562 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5563 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5564 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5565 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5566 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5567
5568 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5569 AssertRC(rc);
5570
5571 uint64_t u64GuestCr3;
5572 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5573 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5574 || CPUMIsGuestPagingEnabledEx(pCtx))
5575 {
5576 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5577 if (CPUMIsGuestInPAEModeEx(pCtx))
5578 {
5579 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5580 AssertRC(rc);
5581 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
5582 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
5583 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
5584 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
5585 }
5586
5587 /*
5588 * The guest's view of its CR3 is unblemished with nested paging when the
5589 * guest is using paging or we have unrestricted guest execution to handle
5590 * the guest when it's not using paging.
5591 */
5592 u64GuestCr3 = pCtx->cr3;
5593 }
5594 else
5595 {
5596 /*
5597 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5598 * thinks it accesses physical memory directly, we use our identity-mapped
5599 * page table to map guest-linear to guest-physical addresses. EPT takes care
5600 * of translating it to host-physical addresses.
5601 */
5602 RTGCPHYS GCPhys;
5603 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5604
5605 /* We obtain it here every time as the guest could have relocated this PCI region. */
5606 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5607 if (RT_SUCCESS(rc))
5608 { /* likely */ }
5609 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5610 {
5611 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5612 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5613 }
5614 else
5615 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5616
5617 u64GuestCr3 = GCPhys;
5618 }
5619
5620 Log4Func(("guest_cr3=%#RX64 (GstN)\n", u64GuestCr3));
5621 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, u64GuestCr3);
5622 AssertRC(rc);
5623 }
5624 else
5625 {
5626 Assert(!pVmxTransient->fIsNestedGuest);
5627 /* Non-nested paging case, just use the hypervisor's CR3. */
5628 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5629
5630 Log4Func(("guest_cr3=%#RX64 (HstN)\n", HCPhysGuestCr3));
5631 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5632 AssertRC(rc);
5633 }
5634
5635 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5636 }
5637
5638 /*
5639 * Guest CR4.
5640 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5641 */
5642 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5643 {
5644 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5645 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5646
5647 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0;
5648 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5649
5650 /*
5651 * With nested-guests, we may have extended the guest/host mask here (since we
5652 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5653 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5654 * the nested hypervisor originally supplied. Thus, we should, in essence, copy
5655 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5656 */
5657 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5658 uint64_t u64GuestCr4 = pCtx->cr4;
5659 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5660 ? pCtx->cr4
5661 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5662 Assert(!RT_HI_U32(u64GuestCr4));
5663
5664 /*
5665 * Setup VT-x's view of the guest CR4.
5666 *
5667 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5668 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5669 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5670 *
5671 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5672 */
5673 if (pVmcsInfo->RealMode.fRealOnV86Active)
5674 {
5675 Assert(pVM->hm.s.vmx.pRealModeTSS);
5676 Assert(PDMVmmDevHeapIsEnabled(pVM));
5677 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5678 }
5679
5680 if (pVM->hm.s.fNestedPaging)
5681 {
5682 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5683 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5684 {
5685 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5686 u64GuestCr4 |= X86_CR4_PSE;
5687 /* Our identity mapping is a 32-bit page directory. */
5688 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5689 }
5690 /* else use guest CR4.*/
5691 }
5692 else
5693 {
5694 Assert(!pVmxTransient->fIsNestedGuest);
5695
5696 /*
5697 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5698 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5699 */
5700 switch (pVCpu->hm.s.enmShadowMode)
5701 {
5702 case PGMMODE_REAL: /* Real-mode. */
5703 case PGMMODE_PROTECTED: /* Protected mode without paging. */
5704 case PGMMODE_32_BIT: /* 32-bit paging. */
5705 {
5706 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5707 break;
5708 }
5709
5710 case PGMMODE_PAE: /* PAE paging. */
5711 case PGMMODE_PAE_NX: /* PAE paging with NX. */
5712 {
5713 u64GuestCr4 |= X86_CR4_PAE;
5714 break;
5715 }
5716
5717 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
5718 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
5719 {
5720#ifdef VBOX_WITH_64_BITS_GUESTS
5721 /* For our assumption in hmR0VmxShouldSwapEferMsr. */
5722 Assert(u64GuestCr4 & X86_CR4_PAE);
5723 break;
5724#endif
5725 }
5726 default:
5727 AssertFailed();
5728 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
5729 }
5730 }
5731
5732 /* Apply the hardware specified CR4 fixed bits (mainly CR4.VMXE). */
5733 u64GuestCr4 |= fSetCr4;
5734 u64GuestCr4 &= fZapCr4;
5735
5736 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
5737 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_CR4, u64GuestCr4); AssertRC(rc);
5738 rc = VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4); AssertRC(rc);
5739
5740 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
5741 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
5742
5743 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
5744
5745 Log4Func(("cr4=%#RX64 shadow=%#RX64 (set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
5746 }
5747 return rc;
5748}
5749
5750
5751/**
5752 * Exports the guest debug registers into the guest-state area in the VMCS.
5753 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
5754 *
5755 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
5756 *
5757 * @returns VBox status code.
5758 * @param pVCpu The cross context virtual CPU structure.
5759 * @param pVmxTransient The VMX-transient structure.
5760 *
5761 * @remarks No-long-jump zone!!!
5762 */
5763static int hmR0VmxExportSharedDebugState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
5764{
5765 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5766
5767 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
5768 * stepping. */
5769 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5770 if (pVmxTransient->fIsNestedGuest)
5771 {
5772 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
5773 AssertRC(rc);
5774
5775 /* Always intercept Mov DRx accesses for the nested-guest for now. */
5776 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5777 rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
5778 AssertRC(rc);
5779 return VINF_SUCCESS;
5780 }
5781
5782#ifdef VBOX_STRICT
5783 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
5784 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
5785 {
5786 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
5787 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
5788 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
5789 }
5790#endif
5791
5792 bool fSteppingDB = false;
5793 bool fInterceptMovDRx = false;
5794 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5795 if (pVCpu->hm.s.fSingleInstruction)
5796 {
5797 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
5798 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5799 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
5800 {
5801 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
5802 Assert(fSteppingDB == false);
5803 }
5804 else
5805 {
5806 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
5807 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
5808 pVCpu->hm.s.fClearTrapFlag = true;
5809 fSteppingDB = true;
5810 }
5811 }
5812
5813 uint64_t u64GuestDr7;
5814 if ( fSteppingDB
5815 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
5816 {
5817 /*
5818 * Use the combined guest and host DRx values found in the hypervisor register set
5819 * because the hypervisor debugger has breakpoints active or someone is single stepping
5820 * on the host side without a monitor trap flag.
5821 *
5822 * Note! DBGF expects a clean DR6 state before executing guest code.
5823 */
5824 if (!CPUMIsHyperDebugStateActive(pVCpu))
5825 {
5826 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
5827 Assert(CPUMIsHyperDebugStateActive(pVCpu));
5828 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
5829 }
5830
5831 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
5832 u64GuestDr7 = CPUMGetHyperDR7(pVCpu);
5833 pVCpu->hm.s.fUsingHyperDR7 = true;
5834 fInterceptMovDRx = true;
5835 }
5836 else
5837 {
5838 /*
5839 * If the guest has enabled debug registers, we need to load them prior to
5840 * executing guest code so they'll trigger at the right time.
5841 */
5842 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
5843 {
5844 if (!CPUMIsGuestDebugStateActive(pVCpu))
5845 {
5846 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
5847 Assert(CPUMIsGuestDebugStateActive(pVCpu));
5848 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
5849 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
5850 }
5851 Assert(!fInterceptMovDRx);
5852 }
5853 else if (!CPUMIsGuestDebugStateActive(pVCpu))
5854 {
5855 /*
5856 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
5857 * must intercept #DB in order to maintain a correct DR6 guest value, and
5858 * because we need to intercept it to prevent nested #DBs from hanging the
5859 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
5860 */
5861 fInterceptMovDRx = true;
5862 }
5863
5864 /* Update DR7 with the actual guest value. */
5865 u64GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
5866 pVCpu->hm.s.fUsingHyperDR7 = false;
5867 }
5868
5869 if (fInterceptMovDRx)
5870 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
5871 else
5872 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
5873
5874 /*
5875 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
5876 * monitor-trap flag and update our cache.
5877 */
5878 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5879 {
5880 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5881 AssertRC(rc);
5882 pVmcsInfo->u32ProcCtls = uProcCtls;
5883 }
5884
5885 /*
5886 * Update guest DR7.
5887 */
5888 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, u64GuestDr7);
5889 AssertRC(rc);
5890
5891 /*
5892 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
5893 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
5894 *
5895 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5896 */
5897 if (fSteppingDB)
5898 {
5899 Assert(pVCpu->hm.s.fSingleInstruction);
5900 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
5901
5902 uint32_t fIntrState = 0;
5903 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
5904 AssertRC(rc);
5905
5906 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
5907 {
5908 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
5909 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
5910 AssertRC(rc);
5911 }
5912 }
5913
5914 return VINF_SUCCESS;
5915}
5916
5917
5918#ifdef VBOX_STRICT
5919/**
5920 * Strict function to validate segment registers.
5921 *
5922 * @param pVCpu The cross context virtual CPU structure.
5923 * @param pVmcsInfo The VMCS info. object.
5924 *
5925 * @remarks Will import guest CR0 on strict builds during validation of
5926 * segments.
5927 */
5928static void hmR0VmxValidateSegmentRegs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
5929{
5930 /*
5931 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
5932 *
5933 * The reason we check for attribute value 0 in this function and not just the unusable bit is
5934 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
5935 * unusable bit and doesn't change the guest-context value.
5936 */
5937 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
5938 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5939 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
5940 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
5941 && ( !CPUMIsGuestInRealModeEx(pCtx)
5942 && !CPUMIsGuestInV86ModeEx(pCtx)))
5943 {
5944 /* Protected mode checks */
5945 /* CS */
5946 Assert(pCtx->cs.Attr.n.u1Present);
5947 Assert(!(pCtx->cs.Attr.u & 0xf00));
5948 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
5949 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
5950 || !(pCtx->cs.Attr.n.u1Granularity));
5951 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
5952 || (pCtx->cs.Attr.n.u1Granularity));
5953 /* CS cannot be loaded with NULL in protected mode. */
5954 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
5955 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
5956 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
5957 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
5958 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
5959 else
5960 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
5961 /* SS */
5962 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5963 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
5964 if ( !(pCtx->cr0 & X86_CR0_PE)
5965 || pCtx->cs.Attr.n.u4Type == 3)
5966 {
5967 Assert(!pCtx->ss.Attr.n.u2Dpl);
5968 }
5969 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
5970 {
5971 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
5972 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
5973 Assert(pCtx->ss.Attr.n.u1Present);
5974 Assert(!(pCtx->ss.Attr.u & 0xf00));
5975 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
5976 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
5977 || !(pCtx->ss.Attr.n.u1Granularity));
5978 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
5979 || (pCtx->ss.Attr.n.u1Granularity));
5980 }
5981 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
5982 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
5983 {
5984 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5985 Assert(pCtx->ds.Attr.n.u1Present);
5986 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
5987 Assert(!(pCtx->ds.Attr.u & 0xf00));
5988 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
5989 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
5990 || !(pCtx->ds.Attr.n.u1Granularity));
5991 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
5992 || (pCtx->ds.Attr.n.u1Granularity));
5993 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
5994 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
5995 }
5996 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
5997 {
5998 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
5999 Assert(pCtx->es.Attr.n.u1Present);
6000 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6001 Assert(!(pCtx->es.Attr.u & 0xf00));
6002 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6003 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6004 || !(pCtx->es.Attr.n.u1Granularity));
6005 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6006 || (pCtx->es.Attr.n.u1Granularity));
6007 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6008 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6009 }
6010 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6011 {
6012 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6013 Assert(pCtx->fs.Attr.n.u1Present);
6014 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6015 Assert(!(pCtx->fs.Attr.u & 0xf00));
6016 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6017 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6018 || !(pCtx->fs.Attr.n.u1Granularity));
6019 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6020 || (pCtx->fs.Attr.n.u1Granularity));
6021 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6022 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6023 }
6024 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6025 {
6026 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6027 Assert(pCtx->gs.Attr.n.u1Present);
6028 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6029 Assert(!(pCtx->gs.Attr.u & 0xf00));
6030 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6031 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6032 || !(pCtx->gs.Attr.n.u1Granularity));
6033 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6034 || (pCtx->gs.Attr.n.u1Granularity));
6035 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6036 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6037 }
6038 /* 64-bit capable CPUs. */
6039 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6040 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6041 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6042 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6043 }
6044 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6045 || ( CPUMIsGuestInRealModeEx(pCtx)
6046 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6047 {
6048 /* Real and v86 mode checks. */
6049 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6050 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6051 if (pVmcsInfo->RealMode.fRealOnV86Active)
6052 {
6053 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6054 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6055 }
6056 else
6057 {
6058 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6059 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6060 }
6061
6062 /* CS */
6063 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6064 Assert(pCtx->cs.u32Limit == 0xffff);
6065 Assert(u32CSAttr == 0xf3);
6066 /* SS */
6067 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6068 Assert(pCtx->ss.u32Limit == 0xffff);
6069 Assert(u32SSAttr == 0xf3);
6070 /* DS */
6071 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6072 Assert(pCtx->ds.u32Limit == 0xffff);
6073 Assert(u32DSAttr == 0xf3);
6074 /* ES */
6075 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6076 Assert(pCtx->es.u32Limit == 0xffff);
6077 Assert(u32ESAttr == 0xf3);
6078 /* FS */
6079 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6080 Assert(pCtx->fs.u32Limit == 0xffff);
6081 Assert(u32FSAttr == 0xf3);
6082 /* GS */
6083 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6084 Assert(pCtx->gs.u32Limit == 0xffff);
6085 Assert(u32GSAttr == 0xf3);
6086 /* 64-bit capable CPUs. */
6087 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6088 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6089 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6090 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6091 }
6092}
6093#endif /* VBOX_STRICT */
6094
6095
6096/**
6097 * Exports a guest segment register into the guest-state area in the VMCS.
6098 *
6099 * @returns VBox status code.
6100 * @param pVCpu The cross context virtual CPU structure.
6101 * @param pVmcsInfo The VMCS info. object.
6102 * @param iSegReg The segment register number (X86_SREG_XXX).
6103 * @param pSelReg Pointer to the segment selector.
6104 *
6105 * @remarks No-long-jump zone!!!
6106 */
6107static int hmR0VmxExportGuestSegReg(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6108{
6109 Assert(iSegReg < X86_SREG_COUNT);
6110 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6111 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6112 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6113 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6114
6115 uint32_t u32Access = pSelReg->Attr.u;
6116 if (pVmcsInfo->RealMode.fRealOnV86Active)
6117 {
6118 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6119 u32Access = 0xf3;
6120 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6121 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6122 RT_NOREF_PV(pVCpu);
6123 }
6124 else
6125 {
6126 /*
6127 * The way to differentiate between whether this is really a null selector or was just
6128 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6129 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6130 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6131 * NULL selectors loaded in protected-mode have their attribute as 0.
6132 */
6133 if (!u32Access)
6134 u32Access = X86DESCATTR_UNUSABLE;
6135 }
6136
6137 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6138 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6139 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6140
6141 /*
6142 * Commit it to the VMCS.
6143 */
6144 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel); AssertRC(rc);
6145 rc = VMXWriteVmcs32(idxLimit, pSelReg->u32Limit); AssertRC(rc);
6146 rc = VMXWriteVmcsNw(idxBase, pSelReg->u64Base); AssertRC(rc);
6147 rc = VMXWriteVmcs32(idxAttr, u32Access); AssertRC(rc);
6148 return VINF_SUCCESS;
6149}
6150
6151
6152/**
6153 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6154 * area in the VMCS.
6155 *
6156 * @returns VBox status code.
6157 * @param pVCpu The cross context virtual CPU structure.
6158 * @param pVmxTransient The VMX-transient structure.
6159 *
6160 * @remarks Will import guest CR0 on strict builds during validation of
6161 * segments.
6162 * @remarks No-long-jump zone!!!
6163 */
6164static int hmR0VmxExportGuestSegRegsXdtr(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6165{
6166 int rc = VERR_INTERNAL_ERROR_5;
6167 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6168 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6169 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6170
6171 /*
6172 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6173 */
6174 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6175 {
6176 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6177 {
6178 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6179 if (pVmcsInfo->RealMode.fRealOnV86Active)
6180 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6181 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6182 AssertRC(rc);
6183 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6184 }
6185
6186 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6187 {
6188 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6189 if (pVmcsInfo->RealMode.fRealOnV86Active)
6190 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6191 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6192 AssertRC(rc);
6193 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6194 }
6195
6196 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6197 {
6198 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6199 if (pVmcsInfo->RealMode.fRealOnV86Active)
6200 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6201 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6202 AssertRC(rc);
6203 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6204 }
6205
6206 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6207 {
6208 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6209 if (pVmcsInfo->RealMode.fRealOnV86Active)
6210 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6211 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6212 AssertRC(rc);
6213 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6214 }
6215
6216 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6217 {
6218 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6219 if (pVmcsInfo->RealMode.fRealOnV86Active)
6220 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6221 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6222 AssertRC(rc);
6223 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6224 }
6225
6226 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6227 {
6228 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6229 if (pVmcsInfo->RealMode.fRealOnV86Active)
6230 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6231 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6232 AssertRC(rc);
6233 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6234 }
6235
6236#ifdef VBOX_STRICT
6237 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6238#endif
6239 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6240 pCtx->cs.Attr.u));
6241 }
6242
6243 /*
6244 * Guest TR.
6245 */
6246 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6247 {
6248 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6249
6250 /*
6251 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6252 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6253 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6254 */
6255 uint16_t u16Sel;
6256 uint32_t u32Limit;
6257 uint64_t u64Base;
6258 uint32_t u32AccessRights;
6259 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6260 {
6261 u16Sel = pCtx->tr.Sel;
6262 u32Limit = pCtx->tr.u32Limit;
6263 u64Base = pCtx->tr.u64Base;
6264 u32AccessRights = pCtx->tr.Attr.u;
6265 }
6266 else
6267 {
6268 Assert(!pVmxTransient->fIsNestedGuest);
6269 Assert(pVM->hm.s.vmx.pRealModeTSS);
6270 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6271
6272 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6273 RTGCPHYS GCPhys;
6274 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6275 AssertRCReturn(rc, rc);
6276
6277 X86DESCATTR DescAttr;
6278 DescAttr.u = 0;
6279 DescAttr.n.u1Present = 1;
6280 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6281
6282 u16Sel = 0;
6283 u32Limit = HM_VTX_TSS_SIZE;
6284 u64Base = GCPhys;
6285 u32AccessRights = DescAttr.u;
6286 }
6287
6288 /* Validate. */
6289 Assert(!(u16Sel & RT_BIT(2)));
6290 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6291 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6292 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6293 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6294 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6295 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6296 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6297 Assert( (u32Limit & 0xfff) == 0xfff
6298 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6299 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6300 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6301
6302 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_TR_SEL, u16Sel); AssertRC(rc);
6303 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit); AssertRC(rc);
6304 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights); AssertRC(rc);
6305 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_TR_BASE, u64Base); AssertRC(rc);
6306
6307 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6308 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6309 }
6310
6311 /*
6312 * Guest GDTR.
6313 */
6314 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6315 {
6316 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6317
6318 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt); AssertRC(rc);
6319 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt); AssertRC(rc);
6320
6321 /* Validate. */
6322 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6323
6324 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6325 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6326 }
6327
6328 /*
6329 * Guest LDTR.
6330 */
6331 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6332 {
6333 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6334
6335 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6336 uint32_t u32Access;
6337 if ( !pVmxTransient->fIsNestedGuest
6338 && !pCtx->ldtr.Attr.u)
6339 u32Access = X86DESCATTR_UNUSABLE;
6340 else
6341 u32Access = pCtx->ldtr.Attr.u;
6342
6343 rc = VMXWriteVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel); AssertRC(rc);
6344 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit); AssertRC(rc);
6345 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access); AssertRC(rc);
6346 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base); AssertRC(rc);
6347
6348 /* Validate. */
6349 if (!(u32Access & X86DESCATTR_UNUSABLE))
6350 {
6351 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6352 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6353 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6354 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6355 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6356 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6357 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6358 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6359 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6360 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6361 }
6362
6363 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6364 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6365 }
6366
6367 /*
6368 * Guest IDTR.
6369 */
6370 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6371 {
6372 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6373
6374 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt); AssertRC(rc);
6375 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt); AssertRC(rc);
6376
6377 /* Validate. */
6378 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6379
6380 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6381 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6382 }
6383
6384 return VINF_SUCCESS;
6385}
6386
6387
6388/**
6389 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6390 * areas.
6391 *
6392 * These MSRs will automatically be loaded to the host CPU on every successful
6393 * VM-entry and stored from the host CPU on every successful VM-exit.
6394 *
6395 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6396 * actual host MSR values are not- updated here for performance reasons. See
6397 * hmR0VmxExportHostMsrs().
6398 *
6399 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6400 *
6401 * @returns VBox status code.
6402 * @param pVCpu The cross context virtual CPU structure.
6403 * @param pVmxTransient The VMX-transient structure.
6404 *
6405 * @remarks No-long-jump zone!!!
6406 */
6407static int hmR0VmxExportGuestMsrs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6408{
6409 AssertPtr(pVCpu);
6410 AssertPtr(pVmxTransient);
6411
6412 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6413 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6414
6415 /*
6416 * MSRs that we use the auto-load/store MSR area in the VMCS.
6417 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs(),
6418 * nothing to do here. The host MSR values are updated when it's safe in
6419 * hmR0VmxLazySaveHostMsrs().
6420 *
6421 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6422 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6423 * emulation. The merged MSR permission bitmap will ensure that we get VM-exits
6424 * for any MSR that are not part of the lazy MSRs so we do not need to place
6425 * those MSRs into the auto-load/store MSR area. Nothing to do here.
6426 */
6427 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6428 {
6429 /* No auto-load/store MSRs currently. */
6430 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6431 }
6432
6433 /*
6434 * Guest Sysenter MSRs.
6435 */
6436 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6437 {
6438 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6439
6440 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6441 {
6442 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6443 AssertRC(rc);
6444 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6445 }
6446
6447 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6448 {
6449 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6450 AssertRC(rc);
6451 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6452 }
6453
6454 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6455 {
6456 int rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6457 AssertRC(rc);
6458 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6459 }
6460 }
6461
6462 /*
6463 * Guest/host EFER MSR.
6464 */
6465 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6466 {
6467 /* Whether we are using the VMCS to swap the EFER MSR must have been
6468 determined earlier while exporting VM-entry/VM-exit controls. */
6469 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6470 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6471
6472 if (hmR0VmxShouldSwapEferMsr(pVCpu, pVmxTransient))
6473 {
6474 /*
6475 * EFER.LME is written by software, while EFER.LMA is set by the CPU to (CR0.PG & EFER.LME).
6476 * This means a guest can set EFER.LME=1 while CR0.PG=0 and EFER.LMA can remain 0.
6477 * VT-x requires that "IA-32e mode guest" VM-entry control must be identical to EFER.LMA
6478 * and to CR0.PG. Without unrestricted execution, CR0.PG (used for VT-x, not the shadow)
6479 * must always be 1. This forces us to effectively clear both EFER.LMA and EFER.LME until
6480 * the guest has also set CR0.PG=1. Otherwise, we would run into an invalid-guest state
6481 * during VM-entry.
6482 */
6483 uint64_t uGuestEferMsr = pCtx->msrEFER;
6484 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6485 {
6486 if (!(pCtx->msrEFER & MSR_K6_EFER_LMA))
6487 uGuestEferMsr &= ~MSR_K6_EFER_LME;
6488 else
6489 Assert((pCtx->msrEFER & (MSR_K6_EFER_LMA | MSR_K6_EFER_LME)) == (MSR_K6_EFER_LMA | MSR_K6_EFER_LME));
6490 }
6491
6492 /*
6493 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6494 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6495 */
6496 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6497 {
6498 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, uGuestEferMsr);
6499 AssertRC(rc);
6500 }
6501 else
6502 {
6503 /*
6504 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6505 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6506 */
6507 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, uGuestEferMsr,
6508 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6509 AssertRCReturn(rc, rc);
6510 }
6511
6512 Log4Func(("efer=%#RX64 shadow=%#RX64\n", uGuestEferMsr, pCtx->msrEFER));
6513 }
6514 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6515 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6516
6517 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6518 }
6519
6520 /*
6521 * Other MSRs.
6522 * Speculation Control (R/W).
6523 */
6524 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6525 {
6526 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6527 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6528 {
6529 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6530 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6531 AssertRCReturn(rc, rc);
6532 }
6533 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6534 }
6535
6536 return VINF_SUCCESS;
6537}
6538
6539
6540/**
6541 * Wrapper for running the guest code in VT-x.
6542 *
6543 * @returns VBox status code, no informational status codes.
6544 * @param pVCpu The cross context virtual CPU structure.
6545 * @param pVmxTransient The VMX-transient structure.
6546 *
6547 * @remarks No-long-jump zone!!!
6548 */
6549DECLINLINE(int) hmR0VmxRunGuest(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient)
6550{
6551 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6552 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6553 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6554
6555 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6556
6557 /*
6558 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6559 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
6560 * callee-saved and thus the need for this XMM wrapper.
6561 *
6562 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
6563 */
6564 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6565 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
6566 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6567#ifdef VBOX_WITH_KERNEL_USING_XMM
6568 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu, pVmcsInfo->pfnStartVM);
6569#else
6570 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, NULL /*pvUnused*/, pVM, pVCpu);
6571#endif
6572 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
6573 return rc;
6574}
6575
6576
6577/**
6578 * Reports world-switch error and dumps some useful debug info.
6579 *
6580 * @param pVCpu The cross context virtual CPU structure.
6581 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
6582 * @param pVmxTransient The VMX-transient structure (only
6583 * exitReason updated).
6584 */
6585static void hmR0VmxReportWorldSwitchError(PVMCPUCC pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
6586{
6587 Assert(pVCpu);
6588 Assert(pVmxTransient);
6589 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
6590
6591 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
6592 switch (rcVMRun)
6593 {
6594 case VERR_VMX_INVALID_VMXON_PTR:
6595 AssertFailed();
6596 break;
6597 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
6598 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
6599 {
6600 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
6601 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
6602 AssertRC(rc);
6603 hmR0VmxReadExitQualVmcs(pVmxTransient);
6604
6605 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
6606 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
6607 Cannot do it here as we may have been long preempted. */
6608
6609#ifdef VBOX_STRICT
6610 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6611 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
6612 pVmxTransient->uExitReason));
6613 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
6614 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
6615 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
6616 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
6617 else
6618 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
6619 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
6620 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
6621
6622 static struct
6623 {
6624 /** Name of the field to log. */
6625 const char *pszName;
6626 /** The VMCS field. */
6627 uint32_t uVmcsField;
6628 /** Whether host support of this field needs to be checked. */
6629 bool fCheckSupport;
6630 } const s_aVmcsFields[] =
6631 {
6632 { "VMX_VMCS32_CTRL_PIN_EXEC", VMX_VMCS32_CTRL_PIN_EXEC, false },
6633 { "VMX_VMCS32_CTRL_PROC_EXEC", VMX_VMCS32_CTRL_PROC_EXEC, false },
6634 { "VMX_VMCS32_CTRL_PROC_EXEC2", VMX_VMCS32_CTRL_PROC_EXEC2, true },
6635 { "VMX_VMCS32_CTRL_ENTRY", VMX_VMCS32_CTRL_ENTRY, false },
6636 { "VMX_VMCS32_CTRL_EXIT", VMX_VMCS32_CTRL_EXIT, false },
6637 { "VMX_VMCS32_CTRL_CR3_TARGET_COUNT", VMX_VMCS32_CTRL_CR3_TARGET_COUNT, false },
6638 { "VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO", VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, false },
6639 { "VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE", VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, false },
6640 { "VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH", VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, false },
6641 { "VMX_VMCS32_CTRL_TPR_THRESHOLD", VMX_VMCS32_CTRL_TPR_THRESHOLD, false },
6642 { "VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, false },
6643 { "VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, false },
6644 { "VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT", VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, false },
6645 { "VMX_VMCS32_CTRL_EXCEPTION_BITMAP", VMX_VMCS32_CTRL_EXCEPTION_BITMAP, false },
6646 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, false },
6647 { "VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH", VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, false },
6648 { "VMX_VMCS_CTRL_CR0_MASK", VMX_VMCS_CTRL_CR0_MASK, false },
6649 { "VMX_VMCS_CTRL_CR0_READ_SHADOW", VMX_VMCS_CTRL_CR0_READ_SHADOW, false },
6650 { "VMX_VMCS_CTRL_CR4_MASK", VMX_VMCS_CTRL_CR4_MASK, false },
6651 { "VMX_VMCS_CTRL_CR4_READ_SHADOW", VMX_VMCS_CTRL_CR4_READ_SHADOW, false },
6652 { "VMX_VMCS64_CTRL_EPTP_FULL", VMX_VMCS64_CTRL_EPTP_FULL, true },
6653 { "VMX_VMCS_GUEST_RIP", VMX_VMCS_GUEST_RIP, false },
6654 { "VMX_VMCS_GUEST_RSP", VMX_VMCS_GUEST_RSP, false },
6655 { "VMX_VMCS_GUEST_RFLAGS", VMX_VMCS_GUEST_RFLAGS, false },
6656 { "VMX_VMCS16_VPID", VMX_VMCS16_VPID, true, },
6657 { "VMX_VMCS_HOST_CR0", VMX_VMCS_HOST_CR0, false },
6658 { "VMX_VMCS_HOST_CR3", VMX_VMCS_HOST_CR3, false },
6659 { "VMX_VMCS_HOST_CR4", VMX_VMCS_HOST_CR4, false },
6660 /* The order of selector fields below are fixed! */
6661 { "VMX_VMCS16_HOST_ES_SEL", VMX_VMCS16_HOST_ES_SEL, false },
6662 { "VMX_VMCS16_HOST_CS_SEL", VMX_VMCS16_HOST_CS_SEL, false },
6663 { "VMX_VMCS16_HOST_SS_SEL", VMX_VMCS16_HOST_SS_SEL, false },
6664 { "VMX_VMCS16_HOST_DS_SEL", VMX_VMCS16_HOST_DS_SEL, false },
6665 { "VMX_VMCS16_HOST_FS_SEL", VMX_VMCS16_HOST_FS_SEL, false },
6666 { "VMX_VMCS16_HOST_GS_SEL", VMX_VMCS16_HOST_GS_SEL, false },
6667 { "VMX_VMCS16_HOST_TR_SEL", VMX_VMCS16_HOST_TR_SEL, false },
6668 /* End of ordered selector fields. */
6669 { "VMX_VMCS_HOST_TR_BASE", VMX_VMCS_HOST_TR_BASE, false },
6670 { "VMX_VMCS_HOST_GDTR_BASE", VMX_VMCS_HOST_GDTR_BASE, false },
6671 { "VMX_VMCS_HOST_IDTR_BASE", VMX_VMCS_HOST_IDTR_BASE, false },
6672 { "VMX_VMCS32_HOST_SYSENTER_CS", VMX_VMCS32_HOST_SYSENTER_CS, false },
6673 { "VMX_VMCS_HOST_SYSENTER_EIP", VMX_VMCS_HOST_SYSENTER_EIP, false },
6674 { "VMX_VMCS_HOST_SYSENTER_ESP", VMX_VMCS_HOST_SYSENTER_ESP, false },
6675 { "VMX_VMCS_HOST_RSP", VMX_VMCS_HOST_RSP, false },
6676 { "VMX_VMCS_HOST_RIP", VMX_VMCS_HOST_RIP, false }
6677 };
6678
6679 RTGDTR HostGdtr;
6680 ASMGetGDTR(&HostGdtr);
6681
6682 uint32_t const cVmcsFields = RT_ELEMENTS(s_aVmcsFields);
6683 for (uint32_t i = 0; i < cVmcsFields; i++)
6684 {
6685 uint32_t const uVmcsField = s_aVmcsFields[i].uVmcsField;
6686
6687 bool fSupported;
6688 if (!s_aVmcsFields[i].fCheckSupport)
6689 fSupported = true;
6690 else
6691 {
6692 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6693 switch (uVmcsField)
6694 {
6695 case VMX_VMCS64_CTRL_EPTP_FULL: fSupported = pVM->hm.s.fNestedPaging; break;
6696 case VMX_VMCS16_VPID: fSupported = pVM->hm.s.vmx.fVpid; break;
6697 case VMX_VMCS32_CTRL_PROC_EXEC2:
6698 fSupported = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
6699 break;
6700 default:
6701 AssertMsgFailedReturnVoid(("Failed to provide VMCS field support for %#RX32\n", uVmcsField));
6702 }
6703 }
6704
6705 if (fSupported)
6706 {
6707 uint8_t const uWidth = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_WIDTH);
6708 switch (uWidth)
6709 {
6710 case VMX_VMCSFIELD_WIDTH_16BIT:
6711 {
6712 uint16_t u16Val;
6713 rc = VMXReadVmcs16(uVmcsField, &u16Val);
6714 AssertRC(rc);
6715 Log4(("%-40s = %#RX16\n", s_aVmcsFields[i].pszName, u16Val));
6716
6717 if ( uVmcsField >= VMX_VMCS16_HOST_ES_SEL
6718 && uVmcsField <= VMX_VMCS16_HOST_TR_SEL)
6719 {
6720 if (u16Val < HostGdtr.cbGdt)
6721 {
6722 /* Order of selectors in s_apszSel is fixed and matches the order in s_aVmcsFields. */
6723 static const char * const s_apszSel[] = { "Host ES", "Host CS", "Host SS", "Host DS",
6724 "Host FS", "Host GS", "Host TR" };
6725 uint8_t const idxSel = RT_BF_GET(uVmcsField, VMX_BF_VMCSFIELD_INDEX);
6726 Assert(idxSel < RT_ELEMENTS(s_apszSel));
6727 PCX86DESCHC pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u16Val & X86_SEL_MASK));
6728 hmR0DumpDescriptor(pDesc, u16Val, s_apszSel[idxSel]);
6729 }
6730 else
6731 Log4((" Selector value exceeds GDT limit!\n"));
6732 }
6733 break;
6734 }
6735
6736 case VMX_VMCSFIELD_WIDTH_32BIT:
6737 {
6738 uint32_t u32Val;
6739 rc = VMXReadVmcs32(uVmcsField, &u32Val);
6740 AssertRC(rc);
6741 Log4(("%-40s = %#RX32\n", s_aVmcsFields[i].pszName, u32Val));
6742 break;
6743 }
6744
6745 case VMX_VMCSFIELD_WIDTH_64BIT:
6746 case VMX_VMCSFIELD_WIDTH_NATURAL:
6747 {
6748 uint64_t u64Val;
6749 rc = VMXReadVmcs64(uVmcsField, &u64Val);
6750 AssertRC(rc);
6751 Log4(("%-40s = %#RX64\n", s_aVmcsFields[i].pszName, u64Val));
6752 break;
6753 }
6754 }
6755 }
6756 }
6757
6758 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
6759 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
6760 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
6761 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
6762 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
6763 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
6764#endif /* VBOX_STRICT */
6765 break;
6766 }
6767
6768 default:
6769 /* Impossible */
6770 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
6771 break;
6772 }
6773}
6774
6775
6776/**
6777 * Sets up the usage of TSC-offsetting and updates the VMCS.
6778 *
6779 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
6780 * VMX-preemption timer.
6781 *
6782 * @returns VBox status code.
6783 * @param pVCpu The cross context virtual CPU structure.
6784 * @param pVmxTransient The VMX-transient structure.
6785 *
6786 * @remarks No-long-jump zone!!!
6787 */
6788static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
6789{
6790 bool fOffsettedTsc;
6791 bool fParavirtTsc;
6792 uint64_t uTscOffset;
6793 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
6794 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
6795
6796 if (pVM->hm.s.vmx.fUsePreemptTimer)
6797 {
6798 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
6799
6800 /* Make sure the returned values have sane upper and lower boundaries. */
6801 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
6802 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
6803 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
6804 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
6805
6806 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
6807 * preemption timers here. We probably need to clamp the preemption timer,
6808 * after converting the timer value to the host. */
6809 uint32_t const cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
6810 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
6811 AssertRC(rc);
6812 }
6813 else
6814 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
6815
6816 if (fParavirtTsc)
6817 {
6818 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
6819 information before every VM-entry, hence disable it for performance sake. */
6820#if 0
6821 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
6822 AssertRC(rc);
6823#endif
6824 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
6825 }
6826
6827 if ( fOffsettedTsc
6828 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
6829 {
6830 if (pVmxTransient->fIsNestedGuest)
6831 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
6832 hmR0VmxSetTscOffsetVmcs(pVmcsInfo, uTscOffset);
6833 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6834 }
6835 else
6836 {
6837 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
6838 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
6839 }
6840}
6841
6842
6843/**
6844 * Gets the IEM exception flags for the specified vector and IDT vectoring /
6845 * VM-exit interruption info type.
6846 *
6847 * @returns The IEM exception flags.
6848 * @param uVector The event vector.
6849 * @param uVmxEventType The VMX event type.
6850 *
6851 * @remarks This function currently only constructs flags required for
6852 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
6853 * and CR2 aspects of an exception are not included).
6854 */
6855static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
6856{
6857 uint32_t fIemXcptFlags;
6858 switch (uVmxEventType)
6859 {
6860 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
6861 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
6862 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
6863 break;
6864
6865 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
6866 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
6867 break;
6868
6869 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
6870 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
6871 break;
6872
6873 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
6874 {
6875 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6876 if (uVector == X86_XCPT_BP)
6877 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
6878 else if (uVector == X86_XCPT_OF)
6879 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
6880 else
6881 {
6882 fIemXcptFlags = 0;
6883 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
6884 }
6885 break;
6886 }
6887
6888 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
6889 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
6890 break;
6891
6892 default:
6893 fIemXcptFlags = 0;
6894 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
6895 break;
6896 }
6897 return fIemXcptFlags;
6898}
6899
6900
6901/**
6902 * Sets an event as a pending event to be injected into the guest.
6903 *
6904 * @param pVCpu The cross context virtual CPU structure.
6905 * @param u32IntInfo The VM-entry interruption-information field.
6906 * @param cbInstr The VM-entry instruction length in bytes (for
6907 * software interrupts, exceptions and privileged
6908 * software exceptions).
6909 * @param u32ErrCode The VM-entry exception error code.
6910 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
6911 * page-fault.
6912 */
6913DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPUCC pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
6914 RTGCUINTPTR GCPtrFaultAddress)
6915{
6916 Assert(!pVCpu->hm.s.Event.fPending);
6917 pVCpu->hm.s.Event.fPending = true;
6918 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
6919 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
6920 pVCpu->hm.s.Event.cbInstr = cbInstr;
6921 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
6922}
6923
6924
6925/**
6926 * Sets an external interrupt as pending-for-injection into the VM.
6927 *
6928 * @param pVCpu The cross context virtual CPU structure.
6929 * @param u8Interrupt The external interrupt vector.
6930 */
6931DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPUCC pVCpu, uint8_t u8Interrupt)
6932{
6933 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
6934 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
6935 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6936 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6937 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6938}
6939
6940
6941/**
6942 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
6943 *
6944 * @param pVCpu The cross context virtual CPU structure.
6945 */
6946DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPUCC pVCpu)
6947{
6948 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
6949 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
6950 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6951 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6952 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6953}
6954
6955
6956/**
6957 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
6958 *
6959 * @param pVCpu The cross context virtual CPU structure.
6960 */
6961DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPUCC pVCpu)
6962{
6963 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
6964 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6965 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
6966 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6967 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6968}
6969
6970
6971/**
6972 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
6973 *
6974 * @param pVCpu The cross context virtual CPU structure.
6975 */
6976DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPUCC pVCpu)
6977{
6978 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
6979 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6980 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6981 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6982 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6983}
6984
6985
6986/**
6987 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
6988 *
6989 * @param pVCpu The cross context virtual CPU structure.
6990 */
6991DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPUCC pVCpu)
6992{
6993 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
6994 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
6995 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
6996 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
6997 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
6998}
6999
7000
7001#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7002/**
7003 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7004 *
7005 * @param pVCpu The cross context virtual CPU structure.
7006 * @param u32ErrCode The error code for the general-protection exception.
7007 */
7008DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7009{
7010 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7011 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7012 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7013 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7014 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7015}
7016
7017
7018/**
7019 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7020 *
7021 * @param pVCpu The cross context virtual CPU structure.
7022 * @param u32ErrCode The error code for the stack exception.
7023 */
7024DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPUCC pVCpu, uint32_t u32ErrCode)
7025{
7026 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7027 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7028 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7029 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7030 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7031}
7032#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7033
7034
7035/**
7036 * Fixes up attributes for the specified segment register.
7037 *
7038 * @param pVCpu The cross context virtual CPU structure.
7039 * @param pSelReg The segment register that needs fixing.
7040 * @param idxSel The VMCS field for the corresponding segment register.
7041 */
7042static void hmR0VmxFixUnusableSegRegAttr(PVMCPUCC pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7043{
7044 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7045
7046 /*
7047 * If VT-x marks the segment as unusable, most other bits remain undefined:
7048 * - For CS the L, D and G bits have meaning.
7049 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7050 * - For the remaining data segments no bits are defined.
7051 *
7052 * The present bit and the unusable bit has been observed to be set at the
7053 * same time (the selector was supposed to be invalid as we started executing
7054 * a V8086 interrupt in ring-0).
7055 *
7056 * What should be important for the rest of the VBox code, is that the P bit is
7057 * cleared. Some of the other VBox code recognizes the unusable bit, but
7058 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7059 * safe side here, we'll strip off P and other bits we don't care about. If
7060 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7061 *
7062 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7063 */
7064#ifdef VBOX_STRICT
7065 uint32_t const uAttr = pSelReg->Attr.u;
7066#endif
7067
7068 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7069 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7070 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7071
7072#ifdef VBOX_STRICT
7073 VMMRZCallRing3Disable(pVCpu);
7074 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7075# ifdef DEBUG_bird
7076 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7077 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7078 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7079# endif
7080 VMMRZCallRing3Enable(pVCpu);
7081 NOREF(uAttr);
7082#endif
7083 RT_NOREF2(pVCpu, idxSel);
7084}
7085
7086
7087/**
7088 * Imports a guest segment register from the current VMCS into the guest-CPU
7089 * context.
7090 *
7091 * @param pVCpu The cross context virtual CPU structure.
7092 * @param iSegReg The segment register number (X86_SREG_XXX).
7093 *
7094 * @remarks Called with interrupts and/or preemption disabled.
7095 */
7096static void hmR0VmxImportGuestSegReg(PVMCPUCC pVCpu, uint8_t iSegReg)
7097{
7098 Assert(iSegReg < X86_SREG_COUNT);
7099
7100 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7101 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7102 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7103 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7104
7105 uint16_t u16Sel;
7106 uint64_t u64Base;
7107 uint32_t u32Limit, u32Attr;
7108 int rc = VMXReadVmcs16(idxSel, &u16Sel); AssertRC(rc);
7109 rc = VMXReadVmcs32(idxLimit, &u32Limit); AssertRC(rc);
7110 rc = VMXReadVmcs32(idxAttr, &u32Attr); AssertRC(rc);
7111 rc = VMXReadVmcsNw(idxBase, &u64Base); AssertRC(rc);
7112
7113 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7114 pSelReg->Sel = u16Sel;
7115 pSelReg->ValidSel = u16Sel;
7116 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7117 pSelReg->u32Limit = u32Limit;
7118 pSelReg->u64Base = u64Base;
7119 pSelReg->Attr.u = u32Attr;
7120 if (u32Attr & X86DESCATTR_UNUSABLE)
7121 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7122}
7123
7124
7125/**
7126 * Imports the guest LDTR from the current VMCS 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.
7131 */
7132static void hmR0VmxImportGuestLdtr(PVMCPUCC pVCpu)
7133{
7134 uint16_t u16Sel;
7135 uint64_t u64Base;
7136 uint32_t u32Limit, u32Attr;
7137 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_LDTR_SEL, &u16Sel); AssertRC(rc);
7138 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit); AssertRC(rc);
7139 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7140 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_LDTR_BASE, &u64Base); AssertRC(rc);
7141
7142 pVCpu->cpum.GstCtx.ldtr.Sel = u16Sel;
7143 pVCpu->cpum.GstCtx.ldtr.ValidSel = u16Sel;
7144 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7145 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7146 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7147 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7148 if (u32Attr & X86DESCATTR_UNUSABLE)
7149 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7150}
7151
7152
7153/**
7154 * Imports the guest TR from the current VMCS into the guest-CPU context.
7155 *
7156 * @param pVCpu The cross context virtual CPU structure.
7157 *
7158 * @remarks Called with interrupts and/or preemption disabled.
7159 */
7160static void hmR0VmxImportGuestTr(PVMCPUCC pVCpu)
7161{
7162 uint16_t u16Sel;
7163 uint64_t u64Base;
7164 uint32_t u32Limit, u32Attr;
7165 int rc = VMXReadVmcs16(VMX_VMCS16_GUEST_TR_SEL, &u16Sel); AssertRC(rc);
7166 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit); AssertRC(rc);
7167 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr); AssertRC(rc);
7168 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_TR_BASE, &u64Base); AssertRC(rc);
7169
7170 pVCpu->cpum.GstCtx.tr.Sel = u16Sel;
7171 pVCpu->cpum.GstCtx.tr.ValidSel = u16Sel;
7172 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7173 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7174 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7175 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7176 /* TR is the only selector that can never be unusable. */
7177 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7178}
7179
7180
7181/**
7182 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7183 *
7184 * @param pVCpu The cross context virtual CPU structure.
7185 *
7186 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7187 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7188 * instead!!!
7189 */
7190static void hmR0VmxImportGuestRip(PVMCPUCC pVCpu)
7191{
7192 uint64_t u64Val;
7193 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7194 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7195 {
7196 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
7197 AssertRC(rc);
7198
7199 pCtx->rip = u64Val;
7200 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7201 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7202 }
7203}
7204
7205
7206/**
7207 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7208 *
7209 * @param pVCpu The cross context virtual CPU structure.
7210 * @param pVmcsInfo The VMCS info. object.
7211 *
7212 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7213 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7214 * instead!!!
7215 */
7216static void hmR0VmxImportGuestRFlags(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7217{
7218 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7219 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7220 {
7221 uint64_t u64Val;
7222 int rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
7223 AssertRC(rc);
7224
7225 pCtx->rflags.u64 = u64Val;
7226 if (pVmcsInfo->RealMode.fRealOnV86Active)
7227 {
7228 pCtx->eflags.Bits.u1VM = 0;
7229 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7230 }
7231 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7232 }
7233}
7234
7235
7236/**
7237 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7238 * context.
7239 *
7240 * @param pVCpu The cross context virtual CPU structure.
7241 * @param pVmcsInfo The VMCS info. object.
7242 *
7243 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7244 * do not log!
7245 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7246 * instead!!!
7247 */
7248static void hmR0VmxImportGuestIntrState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
7249{
7250 uint32_t u32Val;
7251 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val); AssertRC(rc);
7252 if (!u32Val)
7253 {
7254 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7255 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7256 CPUMSetGuestNmiBlocking(pVCpu, false);
7257 }
7258 else
7259 {
7260 /*
7261 * We must import RIP here to set our EM interrupt-inhibited state.
7262 * We also import RFLAGS as our code that evaluates pending interrupts
7263 * before VM-entry requires it.
7264 */
7265 hmR0VmxImportGuestRip(pVCpu);
7266 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7267
7268 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7269 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7270 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7271 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7272
7273 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7274 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7275 }
7276}
7277
7278
7279/**
7280 * Worker for VMXR0ImportStateOnDemand.
7281 *
7282 * @returns VBox status code.
7283 * @param pVCpu The cross context virtual CPU structure.
7284 * @param pVmcsInfo The VMCS info. object.
7285 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7286 */
7287static int hmR0VmxImportGuestState(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7288{
7289 int rc = VINF_SUCCESS;
7290 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7291 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7292 uint32_t u32Val;
7293
7294 /*
7295 * Note! This is hack to workaround a mysterious BSOD observed with release builds
7296 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
7297 * neither are other host platforms.
7298 *
7299 * Committing this temporarily as it prevents BSOD.
7300 *
7301 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
7302 */
7303#ifdef RT_OS_WINDOWS
7304 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
7305 return VERR_HM_IPE_1;
7306#endif
7307
7308 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
7309
7310 /*
7311 * We disable interrupts to make the updating of the state and in particular
7312 * the fExtrn modification atomic wrt to preemption hooks.
7313 */
7314 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
7315
7316 fWhat &= pCtx->fExtrn;
7317 if (fWhat)
7318 {
7319 do
7320 {
7321 if (fWhat & CPUMCTX_EXTRN_RIP)
7322 hmR0VmxImportGuestRip(pVCpu);
7323
7324 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
7325 hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7326
7327 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
7328 hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
7329
7330 if (fWhat & CPUMCTX_EXTRN_RSP)
7331 {
7332 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RSP, &pCtx->rsp);
7333 AssertRC(rc);
7334 }
7335
7336 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
7337 {
7338 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
7339 if (fWhat & CPUMCTX_EXTRN_CS)
7340 {
7341 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
7342 hmR0VmxImportGuestRip(pVCpu);
7343 if (fRealOnV86Active)
7344 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
7345 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
7346 }
7347 if (fWhat & CPUMCTX_EXTRN_SS)
7348 {
7349 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
7350 if (fRealOnV86Active)
7351 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
7352 }
7353 if (fWhat & CPUMCTX_EXTRN_DS)
7354 {
7355 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
7356 if (fRealOnV86Active)
7357 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
7358 }
7359 if (fWhat & CPUMCTX_EXTRN_ES)
7360 {
7361 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
7362 if (fRealOnV86Active)
7363 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
7364 }
7365 if (fWhat & CPUMCTX_EXTRN_FS)
7366 {
7367 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
7368 if (fRealOnV86Active)
7369 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
7370 }
7371 if (fWhat & CPUMCTX_EXTRN_GS)
7372 {
7373 hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
7374 if (fRealOnV86Active)
7375 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
7376 }
7377 }
7378
7379 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
7380 {
7381 if (fWhat & CPUMCTX_EXTRN_LDTR)
7382 hmR0VmxImportGuestLdtr(pVCpu);
7383
7384 if (fWhat & CPUMCTX_EXTRN_GDTR)
7385 {
7386 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &pCtx->gdtr.pGdt); AssertRC(rc);
7387 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val); AssertRC(rc);
7388 pCtx->gdtr.cbGdt = u32Val;
7389 }
7390
7391 /* Guest IDTR. */
7392 if (fWhat & CPUMCTX_EXTRN_IDTR)
7393 {
7394 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &pCtx->idtr.pIdt); AssertRC(rc);
7395 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val); AssertRC(rc);
7396 pCtx->idtr.cbIdt = u32Val;
7397 }
7398
7399 /* Guest TR. */
7400 if (fWhat & CPUMCTX_EXTRN_TR)
7401 {
7402 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
7403 don't need to import that one. */
7404 if (!pVmcsInfo->RealMode.fRealOnV86Active)
7405 hmR0VmxImportGuestTr(pVCpu);
7406 }
7407 }
7408
7409 if (fWhat & CPUMCTX_EXTRN_DR7)
7410 {
7411 if (!pVCpu->hm.s.fUsingHyperDR7)
7412 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_DR7, &pCtx->dr[7]); AssertRC(rc);
7413 }
7414
7415 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
7416 {
7417 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip); AssertRC(rc);
7418 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp); AssertRC(rc);
7419 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val); AssertRC(rc);
7420 pCtx->SysEnter.cs = u32Val;
7421 }
7422
7423 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
7424 {
7425 if ( pVM->hm.s.fAllow64BitGuests
7426 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7427 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
7428 }
7429
7430 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
7431 {
7432 if ( pVM->hm.s.fAllow64BitGuests
7433 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
7434 {
7435 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
7436 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
7437 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
7438 }
7439 }
7440
7441 if (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
7442 {
7443 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
7444 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
7445 Assert(pMsrs);
7446 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
7447 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
7448 for (uint32_t i = 0; i < cMsrs; i++)
7449 {
7450 uint32_t const idMsr = pMsrs[i].u32Msr;
7451 switch (idMsr)
7452 {
7453 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
7454 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
7455 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
7456 default:
7457 {
7458 pCtx->fExtrn = 0;
7459 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
7460 ASMSetFlags(fEFlags);
7461 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
7462 return VERR_HM_UNEXPECTED_LD_ST_MSR;
7463 }
7464 }
7465 }
7466 }
7467
7468 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
7469 {
7470 if (fWhat & CPUMCTX_EXTRN_CR0)
7471 {
7472 uint64_t u64Cr0;
7473 uint64_t u64Shadow;
7474 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Cr0); AssertRC(rc);
7475 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow); AssertRC(rc);
7476#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7477 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7478 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7479#else
7480 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7481 {
7482 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7483 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
7484 }
7485 else
7486 {
7487 /*
7488 * We've merged the guest and nested-guest's CR0 guest/host mask while executing
7489 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7490 * re-construct CR0. See @bugref{9180#c95} for details.
7491 */
7492 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7493 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7494 u64Cr0 = (u64Cr0 & ~pVmcsInfo->u64Cr0Mask)
7495 | (pVmcsNstGst->u64GuestCr0.u & pVmcsNstGst->u64Cr0Mask.u)
7496 | (u64Shadow & (pVmcsInfoGst->u64Cr0Mask & ~pVmcsNstGst->u64Cr0Mask.u));
7497 }
7498#endif
7499 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
7500 CPUMSetGuestCR0(pVCpu, u64Cr0);
7501 VMMRZCallRing3Enable(pVCpu);
7502 }
7503
7504 if (fWhat & CPUMCTX_EXTRN_CR4)
7505 {
7506 uint64_t u64Cr4;
7507 uint64_t u64Shadow;
7508 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64Cr4); AssertRC(rc);
7509 rc |= VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow); AssertRC(rc);
7510#ifndef VBOX_WITH_NESTED_HWVIRT_VMX
7511 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7512 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7513#else
7514 if (!CPUMIsGuestInVmxNonRootMode(pCtx))
7515 {
7516 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7517 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
7518 }
7519 else
7520 {
7521 /*
7522 * We've merged the guest and nested-guest's CR4 guest/host mask while executing
7523 * the nested-guest using hardware-assisted VMX. Accordingly we need to
7524 * re-construct CR4. See @bugref{9180#c95} for details.
7525 */
7526 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
7527 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
7528 u64Cr4 = (u64Cr4 & ~pVmcsInfo->u64Cr4Mask)
7529 | (pVmcsNstGst->u64GuestCr4.u & pVmcsNstGst->u64Cr4Mask.u)
7530 | (u64Shadow & (pVmcsInfoGst->u64Cr4Mask & ~pVmcsNstGst->u64Cr4Mask.u));
7531 }
7532#endif
7533 pCtx->cr4 = u64Cr4;
7534 }
7535
7536 if (fWhat & CPUMCTX_EXTRN_CR3)
7537 {
7538 /* CR0.PG bit changes are always intercepted, so it's up to date. */
7539 if ( pVM->hm.s.vmx.fUnrestrictedGuest
7540 || ( pVM->hm.s.fNestedPaging
7541 && CPUMIsGuestPagingEnabledEx(pCtx)))
7542 {
7543 uint64_t u64Cr3;
7544 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR3, &u64Cr3); AssertRC(rc);
7545 if (pCtx->cr3 != u64Cr3)
7546 {
7547 pCtx->cr3 = u64Cr3;
7548 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
7549 }
7550
7551 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
7552 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
7553 if (CPUMIsGuestInPAEModeEx(pCtx))
7554 {
7555 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u); AssertRC(rc);
7556 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u); AssertRC(rc);
7557 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u); AssertRC(rc);
7558 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u); AssertRC(rc);
7559 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
7560 }
7561 }
7562 }
7563 }
7564
7565#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7566 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
7567 {
7568 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
7569 && !CPUMIsGuestInVmxNonRootMode(pCtx))
7570 {
7571 Assert(CPUMIsGuestInVmxRootMode(pCtx));
7572 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
7573 if (RT_SUCCESS(rc))
7574 { /* likely */ }
7575 else
7576 break;
7577 }
7578 }
7579#endif
7580 } while (0);
7581
7582 if (RT_SUCCESS(rc))
7583 {
7584 /* Update fExtrn. */
7585 pCtx->fExtrn &= ~fWhat;
7586
7587 /* If everything has been imported, clear the HM keeper bit. */
7588 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
7589 {
7590 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
7591 Assert(!pCtx->fExtrn);
7592 }
7593 }
7594 }
7595 else
7596 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
7597
7598 /*
7599 * Restore interrupts.
7600 */
7601 ASMSetFlags(fEFlags);
7602
7603 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
7604
7605 if (RT_SUCCESS(rc))
7606 { /* likely */ }
7607 else
7608 return rc;
7609
7610 /*
7611 * Honor any pending CR3 updates.
7612 *
7613 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> VMXR0CallRing3Callback()
7614 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
7615 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
7616 *
7617 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
7618 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
7619 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
7620 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
7621 *
7622 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
7623 */
7624 if (VMMRZCallRing3IsEnabled(pVCpu))
7625 {
7626 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
7627 {
7628 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
7629 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
7630 }
7631
7632 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
7633 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
7634
7635 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
7636 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
7637 }
7638
7639 return VINF_SUCCESS;
7640}
7641
7642
7643/**
7644 * Saves the guest state from the VMCS into the guest-CPU context.
7645 *
7646 * @returns VBox status code.
7647 * @param pVCpu The cross context virtual CPU structure.
7648 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7649 */
7650VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPUCC pVCpu, uint64_t fWhat)
7651{
7652 AssertPtr(pVCpu);
7653 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7654 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
7655}
7656
7657
7658/**
7659 * Check per-VM and per-VCPU force flag actions that require us to go back to
7660 * ring-3 for one reason or another.
7661 *
7662 * @returns Strict VBox status code (i.e. informational status codes too)
7663 * @retval VINF_SUCCESS if we don't have any actions that require going back to
7664 * ring-3.
7665 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
7666 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
7667 * interrupts)
7668 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
7669 * all EMTs to be in ring-3.
7670 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
7671 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
7672 * to the EM loop.
7673 *
7674 * @param pVCpu The cross context virtual CPU structure.
7675 * @param fStepping Whether we are single-stepping the guest using the
7676 * hypervisor debugger.
7677 *
7678 * @remarks This might cause nested-guest VM-exits, caller must check if the guest
7679 * is no longer in VMX non-root mode.
7680 */
7681static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPUCC pVCpu, bool fStepping)
7682{
7683 Assert(VMMRZCallRing3IsEnabled(pVCpu));
7684
7685 /*
7686 * Update pending interrupts into the APIC's IRR.
7687 */
7688 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
7689 APICUpdatePendingInterrupts(pVCpu);
7690
7691 /*
7692 * Anything pending? Should be more likely than not if we're doing a good job.
7693 */
7694 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
7695 if ( !fStepping
7696 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
7697 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
7698 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
7699 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
7700 return VINF_SUCCESS;
7701
7702 /* Pending PGM C3 sync. */
7703 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
7704 {
7705 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7706 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
7707 VBOXSTRICTRC rcStrict = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
7708 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
7709 if (rcStrict != VINF_SUCCESS)
7710 {
7711 AssertRC(VBOXSTRICTRC_VAL(rcStrict));
7712 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict)));
7713 return rcStrict;
7714 }
7715 }
7716
7717 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
7718 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
7719 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
7720 {
7721 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
7722 int rc = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
7723 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc));
7724 return rc;
7725 }
7726
7727 /* Pending VM request packets, such as hardware interrupts. */
7728 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
7729 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
7730 {
7731 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
7732 Log4Func(("Pending VM request forcing us back to ring-3\n"));
7733 return VINF_EM_PENDING_REQUEST;
7734 }
7735
7736 /* Pending PGM pool flushes. */
7737 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
7738 {
7739 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
7740 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
7741 return VINF_PGM_POOL_FLUSH_PENDING;
7742 }
7743
7744 /* Pending DMA requests. */
7745 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
7746 {
7747 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
7748 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
7749 return VINF_EM_RAW_TO_R3;
7750 }
7751
7752#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7753 /* Pending nested-guest APIC-write (has highest priority among nested-guest FFs). */
7754 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_VMX_APIC_WRITE))
7755 {
7756 Log4Func(("Pending nested-guest APIC-write\n"));
7757 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitApicWrite(pVCpu);
7758 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
7759 return rcStrict;
7760 }
7761 /** @todo VMCPU_FF_VMX_MTF, VMCPU_FF_VMX_PREEMPT_TIMER */
7762#endif
7763
7764 return VINF_SUCCESS;
7765}
7766
7767
7768/**
7769 * Converts any TRPM trap into a pending HM event. This is typically used when
7770 * entering from ring-3 (not longjmp returns).
7771 *
7772 * @param pVCpu The cross context virtual CPU structure.
7773 */
7774static void hmR0VmxTrpmTrapToPendingEvent(PVMCPUCC pVCpu)
7775{
7776 Assert(TRPMHasTrap(pVCpu));
7777 Assert(!pVCpu->hm.s.Event.fPending);
7778
7779 uint8_t uVector;
7780 TRPMEVENT enmTrpmEvent;
7781 uint32_t uErrCode;
7782 RTGCUINTPTR GCPtrFaultAddress;
7783 uint8_t cbInstr;
7784 bool fIcebp;
7785
7786 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr, &fIcebp);
7787 AssertRC(rc);
7788
7789 uint32_t u32IntInfo;
7790 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
7791 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent, fIcebp);
7792
7793 rc = TRPMResetTrap(pVCpu);
7794 AssertRC(rc);
7795 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
7796 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
7797
7798 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
7799}
7800
7801
7802/**
7803 * Converts the pending HM event into a TRPM trap.
7804 *
7805 * @param pVCpu The cross context virtual CPU structure.
7806 */
7807static void hmR0VmxPendingEventToTrpmTrap(PVMCPUCC pVCpu)
7808{
7809 Assert(pVCpu->hm.s.Event.fPending);
7810
7811 /* If a trap was already pending, we did something wrong! */
7812 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
7813
7814 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
7815 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
7816 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
7817
7818 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
7819
7820 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
7821 AssertRC(rc);
7822
7823 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
7824 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
7825
7826 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
7827 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
7828 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
7829 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
7830
7831 if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
7832 TRPMSetTrapDueToIcebp(pVCpu);
7833
7834 /* We're now done converting the pending event. */
7835 pVCpu->hm.s.Event.fPending = false;
7836}
7837
7838
7839/**
7840 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
7841 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
7842 *
7843 * @param pVCpu The cross context virtual CPU structure.
7844 * @param pVmcsInfo The VMCS info. object.
7845 */
7846static void hmR0VmxSetIntWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7847{
7848 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7849 {
7850 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
7851 {
7852 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
7853 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7854 AssertRC(rc);
7855 }
7856 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
7857}
7858
7859
7860/**
7861 * Clears the interrupt-window exiting control in the VMCS.
7862 *
7863 * @param pVmcsInfo The VMCS info. object.
7864 */
7865DECLINLINE(void) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7866{
7867 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
7868 {
7869 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
7870 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7871 AssertRC(rc);
7872 }
7873}
7874
7875
7876/**
7877 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
7878 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
7879 *
7880 * @param pVCpu The cross context virtual CPU structure.
7881 * @param pVmcsInfo The VMCS info. object.
7882 */
7883static void hmR0VmxSetNmiWindowExitVmcs(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo)
7884{
7885 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7886 {
7887 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
7888 {
7889 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7890 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7891 AssertRC(rc);
7892 Log4Func(("Setup NMI-window exiting\n"));
7893 }
7894 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
7895}
7896
7897
7898/**
7899 * Clears the NMI-window exiting control in the VMCS.
7900 *
7901 * @param pVmcsInfo The VMCS info. object.
7902 */
7903DECLINLINE(void) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
7904{
7905 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
7906 {
7907 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
7908 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
7909 AssertRC(rc);
7910 }
7911}
7912
7913
7914/**
7915 * Does the necessary state syncing before returning to ring-3 for any reason
7916 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
7917 *
7918 * @returns VBox status code.
7919 * @param pVCpu The cross context virtual CPU structure.
7920 * @param fImportState Whether to import the guest state from the VMCS back
7921 * to the guest-CPU context.
7922 *
7923 * @remarks No-long-jmp zone!!!
7924 */
7925static int hmR0VmxLeave(PVMCPUCC pVCpu, bool fImportState)
7926{
7927 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
7928 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
7929
7930 RTCPUID const idCpu = RTMpCpuId();
7931 Log4Func(("HostCpuId=%u\n", idCpu));
7932
7933 /*
7934 * !!! IMPORTANT !!!
7935 * If you modify code here, check whether VMXR0CallRing3Callback() needs to be updated too.
7936 */
7937
7938 /* Save the guest state if necessary. */
7939 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7940 if (fImportState)
7941 {
7942 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
7943 AssertRCReturn(rc, rc);
7944 }
7945
7946 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
7947 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
7948 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
7949
7950 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
7951#ifdef VBOX_STRICT
7952 if (CPUMIsHyperDebugStateActive(pVCpu))
7953 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
7954#endif
7955 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
7956 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
7957 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
7958
7959 /* Restore host-state bits that VT-x only restores partially. */
7960 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
7961 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
7962 {
7963 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
7964 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
7965 }
7966 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
7967
7968 /* Restore the lazy host MSRs as we're leaving VT-x context. */
7969 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
7970 {
7971 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
7972 if (!fImportState)
7973 {
7974 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
7975 AssertRCReturn(rc, rc);
7976 }
7977 hmR0VmxLazyRestoreHostMsrs(pVCpu);
7978 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
7979 }
7980 else
7981 pVCpu->hm.s.vmx.fLazyMsrs = 0;
7982
7983 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
7984 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
7985
7986 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
7987 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
7988 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
7989 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
7990 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
7991 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
7992 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
7993 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
7994 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
7995 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
7996
7997 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
7998
7999 /** @todo This partially defeats the purpose of having preemption hooks.
8000 * The problem is, deregistering the hooks should be moved to a place that
8001 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8002 * context.
8003 */
8004 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8005 AssertRCReturn(rc, rc);
8006
8007#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8008 /*
8009 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8010 * clear a shadow VMCS before allowing that VMCS to become active on another
8011 * logical processor. We may or may not be importing guest state which clears
8012 * it, so cover for it here.
8013 *
8014 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8015 */
8016 if ( pVmcsInfo->pvShadowVmcs
8017 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8018 {
8019 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8020 AssertRCReturn(rc, rc);
8021 }
8022
8023 /*
8024 * Flag that we need to re-export the host state if we switch to this VMCS before
8025 * executing guest or nested-guest code.
8026 */
8027 pVmcsInfo->idHostCpuState = NIL_RTCPUID;
8028#endif
8029
8030 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8031 NOREF(idCpu);
8032 return VINF_SUCCESS;
8033}
8034
8035
8036/**
8037 * Leaves the VT-x session.
8038 *
8039 * @returns VBox status code.
8040 * @param pVCpu The cross context virtual CPU structure.
8041 *
8042 * @remarks No-long-jmp zone!!!
8043 */
8044static int hmR0VmxLeaveSession(PVMCPUCC pVCpu)
8045{
8046 HM_DISABLE_PREEMPT(pVCpu);
8047 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8048 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8049 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8050
8051 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8052 and done this from the VMXR0ThreadCtxCallback(). */
8053 if (!pVCpu->hm.s.fLeaveDone)
8054 {
8055 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8056 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8057 pVCpu->hm.s.fLeaveDone = true;
8058 }
8059 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8060
8061 /*
8062 * !!! IMPORTANT !!!
8063 * If you modify code here, make sure to check whether VMXR0CallRing3Callback() needs to be updated too.
8064 */
8065
8066 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8067 /** @todo Deregistering here means we need to VMCLEAR always
8068 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8069 * for calling VMMR0ThreadCtxHookDisable here! */
8070 VMMR0ThreadCtxHookDisable(pVCpu);
8071
8072 /* Leave HM context. This takes care of local init (term) and deregistering the longjmp-to-ring-3 callback. */
8073 int rc = HMR0LeaveCpu(pVCpu);
8074 HM_RESTORE_PREEMPT();
8075 return rc;
8076}
8077
8078
8079/**
8080 * Does the necessary state syncing before doing a longjmp to ring-3.
8081 *
8082 * @returns VBox status code.
8083 * @param pVCpu The cross context virtual CPU structure.
8084 *
8085 * @remarks No-long-jmp zone!!!
8086 */
8087DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPUCC pVCpu)
8088{
8089 return hmR0VmxLeaveSession(pVCpu);
8090}
8091
8092
8093/**
8094 * Take necessary actions before going back to ring-3.
8095 *
8096 * An action requires us to go back to ring-3. This function does the necessary
8097 * steps before we can safely return to ring-3. This is not the same as longjmps
8098 * to ring-3, this is voluntary and prepares the guest so it may continue
8099 * executing outside HM (recompiler/IEM).
8100 *
8101 * @returns VBox status code.
8102 * @param pVCpu The cross context virtual CPU structure.
8103 * @param rcExit The reason for exiting to ring-3. Can be
8104 * VINF_VMM_UNKNOWN_RING3_CALL.
8105 */
8106static int hmR0VmxExitToRing3(PVMCPUCC pVCpu, VBOXSTRICTRC rcExit)
8107{
8108 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8109
8110 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8111 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8112 {
8113 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8114 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8115 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8116 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8117 }
8118
8119 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8120 VMMRZCallRing3Disable(pVCpu);
8121 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8122
8123 /*
8124 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8125 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8126 *
8127 * This is because execution may continue from ring-3 and we would need to inject
8128 * the event from there (hence place it back in TRPM).
8129 */
8130 if (pVCpu->hm.s.Event.fPending)
8131 {
8132 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8133 Assert(!pVCpu->hm.s.Event.fPending);
8134
8135 /* Clear the events from the VMCS. */
8136 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8137 AssertRC(rc);
8138 }
8139#ifdef VBOX_STRICT
8140 else
8141 {
8142 /*
8143 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8144 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8145 * occasionally, see @bugref{9180#c42}.
8146 *
8147 * However, if the VM-entry failed, any VM entry-interruption info. field would
8148 * be left unmodified as the event would not have been injected to the guest. In
8149 * such cases, don't assert, we're not going to continue guest execution anyway.
8150 */
8151 uint32_t uExitReason;
8152 uint32_t uEntryIntInfo;
8153 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8154 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8155 AssertRC(rc);
8156 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8157 }
8158#endif
8159
8160 /*
8161 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8162 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8163 * (e.g. TPR below threshold).
8164 */
8165 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8166 {
8167 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8168 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8169 }
8170
8171 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8172 and if we're injecting an event we should have a TRPM trap pending. */
8173 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8174#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8175 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8176#endif
8177
8178 /* Save guest state and restore host state bits. */
8179 int rc = hmR0VmxLeaveSession(pVCpu);
8180 AssertRCReturn(rc, rc);
8181 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8182
8183 /* Thread-context hooks are unregistered at this point!!! */
8184 /* Ring-3 callback notifications are unregistered at this point!!! */
8185
8186 /* Sync recompiler state. */
8187 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8188 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8189 | CPUM_CHANGED_LDTR
8190 | CPUM_CHANGED_GDTR
8191 | CPUM_CHANGED_IDTR
8192 | CPUM_CHANGED_TR
8193 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8194 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8195 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8196 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8197
8198 Assert(!pVCpu->hm.s.fClearTrapFlag);
8199
8200 /* Update the exit-to-ring 3 reason. */
8201 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8202
8203 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8204 if ( rcExit != VINF_EM_RAW_INTERRUPT
8205 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8206 {
8207 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8208 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8209 }
8210
8211 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8212 VMMRZCallRing3Enable(pVCpu);
8213 return rc;
8214}
8215
8216
8217/**
8218 * VMMRZCallRing3() callback wrapper which saves the guest state before we
8219 * longjump to ring-3 and possibly get preempted.
8220 *
8221 * @returns VBox status code.
8222 * @param pVCpu The cross context virtual CPU structure.
8223 * @param enmOperation The operation causing the ring-3 longjump.
8224 */
8225VMMR0DECL(int) VMXR0CallRing3Callback(PVMCPUCC pVCpu, VMMCALLRING3 enmOperation)
8226{
8227 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
8228 {
8229 /*
8230 * !!! IMPORTANT !!!
8231 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
8232 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
8233 */
8234 VMMRZCallRing3RemoveNotification(pVCpu);
8235 VMMRZCallRing3Disable(pVCpu);
8236 HM_DISABLE_PREEMPT(pVCpu);
8237
8238 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8239 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8240 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8241 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8242
8243 /* Restore host-state bits that VT-x only restores partially. */
8244 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8245 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8246 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8247 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8248
8249 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8250 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8251 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8252
8253 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8254 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8255 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8256
8257 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
8258 cleared as part of importing the guest state above. */
8259 hmR0VmxClearVmcs(pVmcsInfo);
8260
8261 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
8262 VMMR0ThreadCtxHookDisable(pVCpu);
8263
8264 /* Leave HM context. This takes care of local init (term). */
8265 HMR0LeaveCpu(pVCpu);
8266 HM_RESTORE_PREEMPT();
8267 return VINF_SUCCESS;
8268 }
8269
8270 Assert(pVCpu);
8271 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8272 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8273
8274 VMMRZCallRing3Disable(pVCpu);
8275 Assert(VMMR0IsLogFlushDisabled(pVCpu));
8276
8277 Log4Func(("-> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
8278
8279 int rc = hmR0VmxLongJmpToRing3(pVCpu);
8280 AssertRCReturn(rc, rc);
8281
8282 VMMRZCallRing3Enable(pVCpu);
8283 return VINF_SUCCESS;
8284}
8285
8286
8287/**
8288 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
8289 * stack.
8290 *
8291 * @returns Strict VBox status code (i.e. informational status codes too).
8292 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
8293 * @param pVCpu The cross context virtual CPU structure.
8294 * @param uValue The value to push to the guest stack.
8295 */
8296static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPUCC pVCpu, uint16_t uValue)
8297{
8298 /*
8299 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
8300 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
8301 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
8302 */
8303 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8304 if (pCtx->sp == 1)
8305 return VINF_EM_RESET;
8306 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
8307 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
8308 AssertRC(rc);
8309 return rc;
8310}
8311
8312
8313/**
8314 * Injects an event into the guest upon VM-entry by updating the relevant fields
8315 * in the VM-entry area in the VMCS.
8316 *
8317 * @returns Strict VBox status code (i.e. informational status codes too).
8318 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
8319 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
8320 *
8321 * @param pVCpu The cross context virtual CPU structure.
8322 * @param pVmxTransient The VMX-transient structure.
8323 * @param pEvent The event being injected.
8324 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
8325 * will be updated if necessary. This cannot not be NULL.
8326 * @param fStepping Whether we're single-stepping guest execution and should
8327 * return VINF_EM_DBG_STEPPED if the event is injected
8328 * directly (registers modified by us, not by hardware on
8329 * VM-entry).
8330 */
8331static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
8332 uint32_t *pfIntrState)
8333{
8334 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
8335 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
8336 Assert(pfIntrState);
8337
8338 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8339 uint32_t u32IntInfo = pEvent->u64IntInfo;
8340 uint32_t const u32ErrCode = pEvent->u32ErrCode;
8341 uint32_t const cbInstr = pEvent->cbInstr;
8342 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
8343 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
8344 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
8345
8346#ifdef VBOX_STRICT
8347 /*
8348 * Validate the error-code-valid bit for hardware exceptions.
8349 * No error codes for exceptions in real-mode.
8350 *
8351 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8352 */
8353 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
8354 && !CPUMIsGuestInRealModeEx(pCtx))
8355 {
8356 switch (uVector)
8357 {
8358 case X86_XCPT_PF:
8359 case X86_XCPT_DF:
8360 case X86_XCPT_TS:
8361 case X86_XCPT_NP:
8362 case X86_XCPT_SS:
8363 case X86_XCPT_GP:
8364 case X86_XCPT_AC:
8365 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
8366 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
8367 RT_FALL_THRU();
8368 default:
8369 break;
8370 }
8371 }
8372
8373 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
8374 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
8375 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
8376#endif
8377
8378 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
8379
8380 /*
8381 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
8382 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
8383 * interrupt handler in the (real-mode) guest.
8384 *
8385 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
8386 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
8387 */
8388 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
8389 {
8390 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
8391 {
8392 /*
8393 * For CPUs with unrestricted guest execution enabled and with the guest
8394 * in real-mode, we must not set the deliver-error-code bit.
8395 *
8396 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
8397 */
8398 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
8399 }
8400 else
8401 {
8402 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
8403 Assert(PDMVmmDevHeapIsEnabled(pVM));
8404 Assert(pVM->hm.s.vmx.pRealModeTSS);
8405 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
8406
8407 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
8408 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8409 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
8410 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
8411 AssertRCReturn(rc2, rc2);
8412
8413 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
8414 size_t const cbIdtEntry = sizeof(X86IDTR16);
8415 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
8416 {
8417 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
8418 if (uVector == X86_XCPT_DF)
8419 return VINF_EM_RESET;
8420
8421 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
8422 No error codes for exceptions in real-mode. */
8423 if (uVector == X86_XCPT_GP)
8424 {
8425 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
8426 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8427 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8428 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8429 HMEVENT EventXcptDf;
8430 RT_ZERO(EventXcptDf);
8431 EventXcptDf.u64IntInfo = uXcptDfInfo;
8432 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
8433 }
8434
8435 /*
8436 * If we're injecting an event with no valid IDT entry, inject a #GP.
8437 * No error codes for exceptions in real-mode.
8438 *
8439 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
8440 */
8441 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
8442 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
8443 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
8444 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
8445 HMEVENT EventXcptGp;
8446 RT_ZERO(EventXcptGp);
8447 EventXcptGp.u64IntInfo = uXcptGpInfo;
8448 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
8449 }
8450
8451 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
8452 uint16_t uGuestIp = pCtx->ip;
8453 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
8454 {
8455 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
8456 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
8457 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8458 }
8459 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
8460 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
8461
8462 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
8463 X86IDTR16 IdtEntry;
8464 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
8465 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
8466 AssertRCReturn(rc2, rc2);
8467
8468 /* Construct the stack frame for the interrupt/exception handler. */
8469 VBOXSTRICTRC rcStrict;
8470 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
8471 if (rcStrict == VINF_SUCCESS)
8472 {
8473 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
8474 if (rcStrict == VINF_SUCCESS)
8475 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
8476 }
8477
8478 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
8479 if (rcStrict == VINF_SUCCESS)
8480 {
8481 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
8482 pCtx->rip = IdtEntry.offSel;
8483 pCtx->cs.Sel = IdtEntry.uSel;
8484 pCtx->cs.ValidSel = IdtEntry.uSel;
8485 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
8486 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
8487 && uVector == X86_XCPT_PF)
8488 pCtx->cr2 = GCPtrFault;
8489
8490 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
8491 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
8492 | HM_CHANGED_GUEST_RSP);
8493
8494 /*
8495 * If we delivered a hardware exception (other than an NMI) and if there was
8496 * block-by-STI in effect, we should clear it.
8497 */
8498 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
8499 {
8500 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
8501 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
8502 Log4Func(("Clearing inhibition due to STI\n"));
8503 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
8504 }
8505
8506 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
8507 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
8508
8509 /*
8510 * The event has been truly dispatched to the guest. Mark it as no longer pending so
8511 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
8512 */
8513 pVCpu->hm.s.Event.fPending = false;
8514
8515 /*
8516 * If we eventually support nested-guest execution without unrestricted guest execution,
8517 * we should set fInterceptEvents here.
8518 */
8519 Assert(!pVmxTransient->fIsNestedGuest);
8520
8521 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
8522 if (fStepping)
8523 rcStrict = VINF_EM_DBG_STEPPED;
8524 }
8525 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
8526 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
8527 return rcStrict;
8528 }
8529 }
8530
8531 /*
8532 * Validate.
8533 */
8534 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
8535 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
8536
8537 /*
8538 * Inject the event into the VMCS.
8539 */
8540 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
8541 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8542 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
8543 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
8544 AssertRC(rc);
8545
8546 /*
8547 * Update guest CR2 if this is a page-fault.
8548 */
8549 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
8550 pCtx->cr2 = GCPtrFault;
8551
8552 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
8553 return VINF_SUCCESS;
8554}
8555
8556
8557/**
8558 * Evaluates the event to be delivered to the guest and sets it as the pending
8559 * event.
8560 *
8561 * @returns Strict VBox status code (i.e. informational status codes too).
8562 * @param pVCpu The cross context virtual CPU structure.
8563 * @param pVmxTransient The VMX-transient structure.
8564 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
8565 */
8566static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
8567{
8568 Assert(pfIntrState);
8569 Assert(!TRPMHasTrap(pVCpu));
8570
8571 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8572 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
8573 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
8574
8575 /*
8576 * Get the current interruptibility-state of the guest or nested-guest and
8577 * then figure out what needs to be injected.
8578 */
8579 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
8580 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8581 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8582 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8583
8584 /* We don't support block-by-SMI yet.*/
8585 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI));
8586
8587 /* Block-by-STI must not be set when interrupts are disabled. */
8588 if (fBlockSti)
8589 {
8590 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
8591 Assert(pCtx->eflags.Bits.u1IF);
8592 }
8593
8594 /* Update interruptibility state to the caller. */
8595 *pfIntrState = fIntrState;
8596
8597 /*
8598 * Toggling of interrupt force-flags here is safe since we update TRPM on
8599 * premature exits to ring-3 before executing guest code, see hmR0VmxExitToRing3().
8600 * We must NOT restore these force-flags.
8601 */
8602
8603 /** @todo SMI. SMIs take priority over NMIs. */
8604
8605 /*
8606 * Check if an NMI is pending and if the guest or nested-guest can receive them.
8607 * NMIs take priority over external interrupts.
8608 */
8609 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI))
8610 {
8611 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
8612 if ( !pVCpu->hm.s.Event.fPending
8613 && !fBlockNmi
8614 && !fBlockSti
8615 && !fBlockMovSS)
8616 {
8617#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8618 if ( fIsNestedGuest
8619 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
8620 return IEMExecVmxVmexitXcptNmi(pVCpu);
8621#endif
8622 hmR0VmxSetPendingXcptNmi(pVCpu);
8623 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
8624 Log4Func(("Pending NMI\n"));
8625 }
8626 else if (!fIsNestedGuest)
8627 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
8628 /* else: for nested-guests, NMI-window exiting will be picked up when merging VMCS controls. */
8629 }
8630 /*
8631 * Check if an external interrupt (PIC/APIC) is pending and if the guest or nested-guest
8632 * can receive them. Once PDMGetInterrupt() returns a valid interrupt we -must- deliver
8633 * the interrupt. We can no longer re-request it from the APIC.
8634 */
8635 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
8636 && !pVCpu->hm.s.fSingleInstruction)
8637 {
8638 Assert(!DBGFIsStepping(pVCpu));
8639 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
8640 AssertRCReturn(rc, rc);
8641
8642 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
8643 if ( !pVCpu->hm.s.Event.fPending
8644 && !fBlockInt
8645 && !fBlockSti
8646 && !fBlockMovSS)
8647 {
8648#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8649 if ( fIsNestedGuest
8650 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8651 && !CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8652 {
8653 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0 /* uVector */, true /* fIntPending */);
8654 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8655 return rcStrict;
8656 }
8657#endif
8658 uint8_t u8Interrupt;
8659 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
8660 if (RT_SUCCESS(rc))
8661 {
8662#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8663 if ( fIsNestedGuest
8664 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
8665 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
8666 {
8667 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
8668 Assert(rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE);
8669 return rcStrict;
8670 }
8671#endif
8672 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
8673 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
8674 }
8675 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
8676 {
8677 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
8678
8679 if ( !fIsNestedGuest
8680 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
8681 hmR0VmxApicSetTprThreshold(pVmcsInfo, u8Interrupt >> 4);
8682 /* else: for nested-guests, TPR threshold is picked up while merging VMCS controls. */
8683
8684 /*
8685 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
8686 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
8687 * need to re-set this force-flag here.
8688 */
8689 }
8690 else
8691 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
8692 }
8693 else if (!fIsNestedGuest)
8694 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
8695 /* else: for nested-guests, interrupt-window exiting will be picked up when merging VMCS controls. */
8696 }
8697
8698 return VINF_SUCCESS;
8699}
8700
8701
8702/**
8703 * Injects any pending events into the guest if the guest is in a state to
8704 * receive them.
8705 *
8706 * @returns Strict VBox status code (i.e. informational status codes too).
8707 * @param pVCpu The cross context virtual CPU structure.
8708 * @param pVmxTransient The VMX-transient structure.
8709 * @param fIntrState The VT-x guest-interruptibility state.
8710 * @param fStepping Whether we are single-stepping the guest using the
8711 * hypervisor debugger and should return
8712 * VINF_EM_DBG_STEPPED if the event was dispatched
8713 * directly.
8714 */
8715static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
8716{
8717 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8718 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8719
8720 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
8721 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
8722
8723 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
8724 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
8725 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
8726 Assert(!TRPMHasTrap(pVCpu));
8727
8728 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
8729 if (pVCpu->hm.s.Event.fPending)
8730 {
8731 /*
8732 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
8733 * pending even while injecting an event and in this case, we want a VM-exit as soon as
8734 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
8735 *
8736 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
8737 */
8738 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
8739#ifdef VBOX_STRICT
8740 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8741 {
8742 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
8743 Assert(!fBlockInt);
8744 Assert(!fBlockSti);
8745 Assert(!fBlockMovSS);
8746 }
8747 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
8748 {
8749 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
8750 Assert(!fBlockSti);
8751 Assert(!fBlockMovSS);
8752 Assert(!fBlockNmi);
8753 }
8754#endif
8755 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
8756 uIntType));
8757
8758 /*
8759 * Inject the event and get any changes to the guest-interruptibility state.
8760 *
8761 * The guest-interruptibility state may need to be updated if we inject the event
8762 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
8763 */
8764 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
8765 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
8766
8767 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
8768 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
8769 else
8770 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
8771 }
8772
8773 /*
8774 * Update the guest-interruptibility state.
8775 *
8776 * This is required for the real-on-v86 software interrupt injection case above, as well as
8777 * updates to the guest state from ring-3 or IEM/REM.
8778 */
8779 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
8780 AssertRC(rc);
8781
8782 /*
8783 * There's no need to clear the VM-entry interruption-information field here if we're not
8784 * injecting anything. VT-x clears the valid bit on every VM-exit.
8785 *
8786 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
8787 */
8788
8789 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
8790 NOREF(fBlockMovSS); NOREF(fBlockSti);
8791 return rcStrict;
8792}
8793
8794
8795/**
8796 * Enters the VT-x session.
8797 *
8798 * @returns VBox status code.
8799 * @param pVCpu The cross context virtual CPU structure.
8800 */
8801VMMR0DECL(int) VMXR0Enter(PVMCPUCC pVCpu)
8802{
8803 AssertPtr(pVCpu);
8804 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
8805 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8806
8807 LogFlowFunc(("pVCpu=%p\n", pVCpu));
8808 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8809 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8810
8811#ifdef VBOX_STRICT
8812 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
8813 RTCCUINTREG uHostCr4 = ASMGetCR4();
8814 if (!(uHostCr4 & X86_CR4_VMXE))
8815 {
8816 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
8817 return VERR_VMX_X86_CR4_VMXE_CLEARED;
8818 }
8819#endif
8820
8821 /*
8822 * Load the appropriate VMCS as the current and active one.
8823 */
8824 PVMXVMCSINFO pVmcsInfo;
8825 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
8826 if (!fInNestedGuestMode)
8827 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
8828 else
8829 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
8830 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
8831 if (RT_SUCCESS(rc))
8832 {
8833 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
8834 pVCpu->hm.s.fLeaveDone = false;
8835 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8836
8837 /*
8838 * Do the EMT scheduled L1D flush here if needed.
8839 */
8840 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8841 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8842 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
8843 hmR0MdsClear();
8844 }
8845 return rc;
8846}
8847
8848
8849/**
8850 * The thread-context callback (only on platforms which support it).
8851 *
8852 * @param enmEvent The thread-context event.
8853 * @param pVCpu The cross context virtual CPU structure.
8854 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
8855 * @thread EMT(pVCpu)
8856 */
8857VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPUCC pVCpu, bool fGlobalInit)
8858{
8859 AssertPtr(pVCpu);
8860 RT_NOREF1(fGlobalInit);
8861
8862 switch (enmEvent)
8863 {
8864 case RTTHREADCTXEVENT_OUT:
8865 {
8866 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8867 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8868 VMCPU_ASSERT_EMT(pVCpu);
8869
8870 /* No longjmps (logger flushes, locks) in this fragile context. */
8871 VMMRZCallRing3Disable(pVCpu);
8872 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
8873
8874 /* Restore host-state (FPU, debug etc.) */
8875 if (!pVCpu->hm.s.fLeaveDone)
8876 {
8877 /*
8878 * Do -not- import the guest-state here as we might already be in the middle of importing
8879 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
8880 */
8881 hmR0VmxLeave(pVCpu, false /* fImportState */);
8882 pVCpu->hm.s.fLeaveDone = true;
8883 }
8884
8885 /* Leave HM context, takes care of local init (term). */
8886 int rc = HMR0LeaveCpu(pVCpu);
8887 AssertRC(rc);
8888
8889 /* Restore longjmp state. */
8890 VMMRZCallRing3Enable(pVCpu);
8891 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
8892 break;
8893 }
8894
8895 case RTTHREADCTXEVENT_IN:
8896 {
8897 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8898 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
8899 VMCPU_ASSERT_EMT(pVCpu);
8900
8901 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
8902 VMMRZCallRing3Disable(pVCpu);
8903 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
8904
8905 /* Initialize the bare minimum state required for HM. This takes care of
8906 initializing VT-x if necessary (onlined CPUs, local init etc.) */
8907 int rc = hmR0EnterCpu(pVCpu);
8908 AssertRC(rc);
8909 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
8910 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
8911
8912 /* Load the active VMCS as the current one. */
8913 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8914 rc = hmR0VmxLoadVmcs(pVmcsInfo);
8915 AssertRC(rc);
8916 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
8917 pVCpu->hm.s.fLeaveDone = false;
8918
8919 /* Do the EMT scheduled L1D flush if needed. */
8920 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
8921 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
8922
8923 /* Restore longjmp state. */
8924 VMMRZCallRing3Enable(pVCpu);
8925 break;
8926 }
8927
8928 default:
8929 break;
8930 }
8931}
8932
8933
8934/**
8935 * Exports the host state into the VMCS host-state area.
8936 * Sets up the VM-exit MSR-load area.
8937 *
8938 * The CPU state will be loaded from these fields on every successful VM-exit.
8939 *
8940 * @returns VBox status code.
8941 * @param pVCpu The cross context virtual CPU structure.
8942 *
8943 * @remarks No-long-jump zone!!!
8944 */
8945static int hmR0VmxExportHostState(PVMCPUCC pVCpu)
8946{
8947 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8948
8949 int rc = VINF_SUCCESS;
8950 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
8951 {
8952 hmR0VmxExportHostControlRegs();
8953
8954 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
8955 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
8956
8957 hmR0VmxExportHostMsrs(pVCpu);
8958
8959 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
8960 }
8961 return rc;
8962}
8963
8964
8965/**
8966 * Saves the host state in the VMCS host-state.
8967 *
8968 * @returns VBox status code.
8969 * @param pVCpu The cross context virtual CPU structure.
8970 *
8971 * @remarks No-long-jump zone!!!
8972 */
8973VMMR0DECL(int) VMXR0ExportHostState(PVMCPUCC pVCpu)
8974{
8975 AssertPtr(pVCpu);
8976 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8977
8978 /*
8979 * Export the host state here while entering HM context.
8980 * When thread-context hooks are used, we might get preempted and have to re-save the host
8981 * state but most of the time we won't be, so do it here before we disable interrupts.
8982 */
8983 return hmR0VmxExportHostState(pVCpu);
8984}
8985
8986
8987/**
8988 * Exports the guest state into the VMCS guest-state area.
8989 *
8990 * The will typically be done before VM-entry when the guest-CPU state and the
8991 * VMCS state may potentially be out of sync.
8992 *
8993 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
8994 * VM-entry controls.
8995 * Sets up the appropriate VMX non-root function to execute guest code based on
8996 * the guest CPU mode.
8997 *
8998 * @returns VBox strict status code.
8999 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9000 * without unrestricted guest execution and the VMMDev is not presently
9001 * mapped (e.g. EFI32).
9002 *
9003 * @param pVCpu The cross context virtual CPU structure.
9004 * @param pVmxTransient The VMX-transient structure.
9005 *
9006 * @remarks No-long-jump zone!!!
9007 */
9008static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9009{
9010 AssertPtr(pVCpu);
9011 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9012 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9013
9014 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9015
9016 /*
9017 * Determine real-on-v86 mode.
9018 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9019 */
9020 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9021 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9022 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9023 pVmcsInfo->RealMode.fRealOnV86Active = false;
9024 else
9025 {
9026 Assert(!pVmxTransient->fIsNestedGuest);
9027 pVmcsInfo->RealMode.fRealOnV86Active = true;
9028 }
9029
9030 /*
9031 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9032 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9033 */
9034 int rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9035 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9036
9037 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9038 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9039
9040 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9041 if (rcStrict == VINF_SUCCESS)
9042 { /* likely */ }
9043 else
9044 {
9045 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9046 return rcStrict;
9047 }
9048
9049 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9050 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9051
9052 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9053 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9054
9055 hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9056 hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9057 hmR0VmxExportGuestRip(pVCpu);
9058 hmR0VmxExportGuestRsp(pVCpu);
9059 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9060
9061 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9062 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9063
9064 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9065 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9066 | HM_CHANGED_GUEST_CR2
9067 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9068 | HM_CHANGED_GUEST_X87
9069 | HM_CHANGED_GUEST_SSE_AVX
9070 | HM_CHANGED_GUEST_OTHER_XSAVE
9071 | HM_CHANGED_GUEST_XCRx
9072 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9073 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9074 | HM_CHANGED_GUEST_TSC_AUX
9075 | HM_CHANGED_GUEST_OTHER_MSRS
9076 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9077
9078 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9079 return rc;
9080}
9081
9082
9083/**
9084 * Exports the state shared between the host and guest into the VMCS.
9085 *
9086 * @param pVCpu The cross context virtual CPU structure.
9087 * @param pVmxTransient The VMX-transient structure.
9088 *
9089 * @remarks No-long-jump zone!!!
9090 */
9091static void hmR0VmxExportSharedState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9092{
9093 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9094 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9095
9096 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9097 {
9098 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9099 AssertRC(rc);
9100 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9101
9102 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9103 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9104 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9105 }
9106
9107 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9108 {
9109 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9110 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9111 }
9112
9113 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9114 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9115}
9116
9117
9118/**
9119 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9120 *
9121 * @returns Strict VBox status code (i.e. informational status codes too).
9122 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9123 * without unrestricted guest execution and the VMMDev is not presently
9124 * mapped (e.g. EFI32).
9125 *
9126 * @param pVCpu The cross context virtual CPU structure.
9127 * @param pVmxTransient The VMX-transient structure.
9128 *
9129 * @remarks No-long-jump zone!!!
9130 */
9131static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
9132{
9133 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9134 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9135 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9136
9137#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9138 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9139#endif
9140
9141 /*
9142 * For many VM-exits only RIP/RSP/RFLAGS (and HWVIRT state when executing a nested-guest)
9143 * changes. First try to export only these without going through all other changed-flag checks.
9144 */
9145 VBOXSTRICTRC rcStrict;
9146 uint64_t const fCtxMask = HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE;
9147 uint64_t const fMinimalMask = HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT;
9148 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9149
9150 /* If only RIP/RSP/RFLAGS/HWVIRT changed, export only those (quicker, happens more often).*/
9151 if ( (fCtxChanged & fMinimalMask)
9152 && !(fCtxChanged & (fCtxMask & ~fMinimalMask)))
9153 {
9154 hmR0VmxExportGuestRip(pVCpu);
9155 hmR0VmxExportGuestRsp(pVCpu);
9156 hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9157 rcStrict = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9158 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9159 }
9160 /* If anything else also changed, go through the full export routine and export as required. */
9161 else if (fCtxChanged & fCtxMask)
9162 {
9163 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9164 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9165 { /* likely */}
9166 else
9167 {
9168 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9169 VBOXSTRICTRC_VAL(rcStrict)));
9170 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9171 return rcStrict;
9172 }
9173 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9174 }
9175 /* Nothing changed, nothing to load here. */
9176 else
9177 rcStrict = VINF_SUCCESS;
9178
9179#ifdef VBOX_STRICT
9180 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9181 uint64_t const fCtxChangedCur = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9182 AssertMsg(!(fCtxChangedCur & fCtxMask), ("fCtxChangedCur=%#RX64\n", fCtxChangedCur));
9183#endif
9184 return rcStrict;
9185}
9186
9187
9188/**
9189 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9190 * and update error record fields accordingly.
9191 *
9192 * @returns VMX_IGS_* error codes.
9193 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9194 * wrong with the guest state.
9195 *
9196 * @param pVCpu The cross context virtual CPU structure.
9197 * @param pVmcsInfo The VMCS info. object.
9198 *
9199 * @remarks This function assumes our cache of the VMCS controls
9200 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9201 */
9202static uint32_t hmR0VmxCheckGuestState(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9203{
9204#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9205#define HMVMX_CHECK_BREAK(expr, err) do { \
9206 if (!(expr)) { uError = (err); break; } \
9207 } while (0)
9208
9209 int rc;
9210 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9211 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9212 uint32_t uError = VMX_IGS_ERROR;
9213 uint32_t u32Val;
9214 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9215
9216 do
9217 {
9218 /*
9219 * CR0.
9220 */
9221 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9222 uint64_t fSetCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9223 uint64_t const fZapCr0 = (pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
9224 /* Exceptions for unrestricted guest execution for CR0 fixed bits (PE, PG).
9225 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
9226 if (fUnrestrictedGuest)
9227 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
9228
9229 uint64_t u64GuestCr0;
9230 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64GuestCr0);
9231 AssertRC(rc);
9232 HMVMX_CHECK_BREAK((u64GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
9233 HMVMX_CHECK_BREAK(!(u64GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
9234 if ( !fUnrestrictedGuest
9235 && (u64GuestCr0 & X86_CR0_PG)
9236 && !(u64GuestCr0 & X86_CR0_PE))
9237 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
9238
9239 /*
9240 * CR4.
9241 */
9242 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
9243 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9244 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
9245
9246 uint64_t u64GuestCr4;
9247 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR4, &u64GuestCr4);
9248 AssertRC(rc);
9249 HMVMX_CHECK_BREAK((u64GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
9250 HMVMX_CHECK_BREAK(!(u64GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
9251
9252 /*
9253 * IA32_DEBUGCTL MSR.
9254 */
9255 uint64_t u64Val;
9256 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
9257 AssertRC(rc);
9258 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9259 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
9260 {
9261 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
9262 }
9263 uint64_t u64DebugCtlMsr = u64Val;
9264
9265#ifdef VBOX_STRICT
9266 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
9267 AssertRC(rc);
9268 Assert(u32Val == pVmcsInfo->u32EntryCtls);
9269#endif
9270 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
9271
9272 /*
9273 * RIP and RFLAGS.
9274 */
9275 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RIP, &u64Val);
9276 AssertRC(rc);
9277 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
9278 if ( !fLongModeGuest
9279 || !pCtx->cs.Attr.n.u1Long)
9280 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
9281 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
9282 * must be identical if the "IA-32e mode guest" VM-entry
9283 * control is 1 and CS.L is 1. No check applies if the
9284 * CPU supports 64 linear-address bits. */
9285
9286 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
9287 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_RFLAGS, &u64Val);
9288 AssertRC(rc);
9289 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
9290 VMX_IGS_RFLAGS_RESERVED);
9291 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
9292 uint32_t const u32Eflags = u64Val;
9293
9294 if ( fLongModeGuest
9295 || ( fUnrestrictedGuest
9296 && !(u64GuestCr0 & X86_CR0_PE)))
9297 {
9298 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
9299 }
9300
9301 uint32_t u32EntryInfo;
9302 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
9303 AssertRC(rc);
9304 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9305 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
9306
9307 /*
9308 * 64-bit checks.
9309 */
9310 if (fLongModeGuest)
9311 {
9312 HMVMX_CHECK_BREAK(u64GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
9313 HMVMX_CHECK_BREAK(u64GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
9314 }
9315
9316 if ( !fLongModeGuest
9317 && (u64GuestCr4 & X86_CR4_PCIDE))
9318 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
9319
9320 /** @todo CR3 field must be such that bits 63:52 and bits in the range
9321 * 51:32 beyond the processor's physical-address width are 0. */
9322
9323 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
9324 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
9325 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
9326
9327 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
9328 AssertRC(rc);
9329 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
9330
9331 rc = VMXReadVmcsNw(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
9332 AssertRC(rc);
9333 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
9334
9335 /*
9336 * PERF_GLOBAL MSR.
9337 */
9338 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
9339 {
9340 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
9341 AssertRC(rc);
9342 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
9343 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
9344 }
9345
9346 /*
9347 * PAT MSR.
9348 */
9349 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
9350 {
9351 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
9352 AssertRC(rc);
9353 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
9354 for (unsigned i = 0; i < 8; i++)
9355 {
9356 uint8_t u8Val = (u64Val & 0xff);
9357 if ( u8Val != 0 /* UC */
9358 && u8Val != 1 /* WC */
9359 && u8Val != 4 /* WT */
9360 && u8Val != 5 /* WP */
9361 && u8Val != 6 /* WB */
9362 && u8Val != 7 /* UC- */)
9363 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
9364 u64Val >>= 8;
9365 }
9366 }
9367
9368 /*
9369 * EFER MSR.
9370 */
9371 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
9372 {
9373 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
9374 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
9375 AssertRC(rc);
9376 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
9377 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
9378 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
9379 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
9380 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
9381 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
9382 * iemVmxVmentryCheckGuestState(). */
9383 HMVMX_CHECK_BREAK( fUnrestrictedGuest
9384 || !(u64GuestCr0 & X86_CR0_PG)
9385 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
9386 VMX_IGS_EFER_LMA_LME_MISMATCH);
9387 }
9388
9389 /*
9390 * Segment registers.
9391 */
9392 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9393 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
9394 if (!(u32Eflags & X86_EFL_VM))
9395 {
9396 /* CS */
9397 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
9398 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
9399 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
9400 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
9401 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9402 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
9403 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
9404 /* CS cannot be loaded with NULL in protected mode. */
9405 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
9406 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
9407 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
9408 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
9409 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
9410 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
9411 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
9412 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
9413 else
9414 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
9415
9416 /* SS */
9417 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9418 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
9419 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
9420 if ( !(pCtx->cr0 & X86_CR0_PE)
9421 || pCtx->cs.Attr.n.u4Type == 3)
9422 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
9423
9424 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
9425 {
9426 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
9427 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
9428 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
9429 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
9430 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
9431 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9432 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
9433 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
9434 }
9435
9436 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
9437 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
9438 {
9439 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
9440 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
9441 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9442 || pCtx->ds.Attr.n.u4Type > 11
9443 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9444 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
9445 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
9446 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
9447 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9448 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
9449 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
9450 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9451 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
9452 }
9453 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
9454 {
9455 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
9456 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
9457 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9458 || pCtx->es.Attr.n.u4Type > 11
9459 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
9460 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
9461 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
9462 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
9463 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9464 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
9465 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
9466 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9467 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
9468 }
9469 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
9470 {
9471 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
9472 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
9473 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9474 || pCtx->fs.Attr.n.u4Type > 11
9475 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
9476 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
9477 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
9478 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
9479 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9480 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
9481 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
9482 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9483 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
9484 }
9485 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
9486 {
9487 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
9488 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
9489 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
9490 || pCtx->gs.Attr.n.u4Type > 11
9491 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
9492 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
9493 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
9494 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
9495 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9496 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
9497 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
9498 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
9499 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
9500 }
9501 /* 64-bit capable CPUs. */
9502 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9503 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9504 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9505 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9506 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9507 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9508 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9509 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9510 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9511 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9512 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9513 }
9514 else
9515 {
9516 /* V86 mode checks. */
9517 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
9518 if (pVmcsInfo->RealMode.fRealOnV86Active)
9519 {
9520 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
9521 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
9522 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
9523 }
9524 else
9525 {
9526 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
9527 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
9528 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
9529 }
9530
9531 /* CS */
9532 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
9533 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
9534 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
9535 /* SS */
9536 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
9537 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
9538 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
9539 /* DS */
9540 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
9541 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
9542 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
9543 /* ES */
9544 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
9545 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
9546 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
9547 /* FS */
9548 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
9549 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
9550 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
9551 /* GS */
9552 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
9553 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
9554 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
9555 /* 64-bit capable CPUs. */
9556 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
9557 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
9558 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
9559 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
9560 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
9561 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
9562 VMX_IGS_LONGMODE_SS_BASE_INVALID);
9563 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
9564 VMX_IGS_LONGMODE_DS_BASE_INVALID);
9565 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
9566 VMX_IGS_LONGMODE_ES_BASE_INVALID);
9567 }
9568
9569 /*
9570 * TR.
9571 */
9572 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
9573 /* 64-bit capable CPUs. */
9574 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
9575 if (fLongModeGuest)
9576 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
9577 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
9578 else
9579 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
9580 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
9581 VMX_IGS_TR_ATTR_TYPE_INVALID);
9582 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
9583 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
9584 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
9585 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
9586 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9587 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
9588 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
9589 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
9590
9591 /*
9592 * GDTR and IDTR (64-bit capable checks).
9593 */
9594 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
9595 AssertRC(rc);
9596 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
9597
9598 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
9599 AssertRC(rc);
9600 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
9601
9602 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
9603 AssertRC(rc);
9604 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9605
9606 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
9607 AssertRC(rc);
9608 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
9609
9610 /*
9611 * Guest Non-Register State.
9612 */
9613 /* Activity State. */
9614 uint32_t u32ActivityState;
9615 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
9616 AssertRC(rc);
9617 HMVMX_CHECK_BREAK( !u32ActivityState
9618 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
9619 VMX_IGS_ACTIVITY_STATE_INVALID);
9620 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
9621 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
9622 uint32_t u32IntrState;
9623 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
9624 AssertRC(rc);
9625 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
9626 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9627 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
9628
9629 /** @todo Activity state and injecting interrupts. Left as a todo since we
9630 * currently don't use activity states but ACTIVE. */
9631
9632 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9633 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
9634
9635 /* Guest interruptibility-state. */
9636 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
9637 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
9638 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9639 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
9640 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
9641 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9642 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
9643 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
9644 {
9645 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9646 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9647 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
9648 }
9649 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9650 {
9651 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
9652 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
9653 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
9654 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
9655 }
9656 /** @todo Assumes the processor is not in SMM. */
9657 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9658 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
9659 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
9660 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
9661 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
9662 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
9663 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
9664 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI), VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
9665
9666 /* Pending debug exceptions. */
9667 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
9668 AssertRC(rc);
9669 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
9670 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
9671 u32Val = u64Val; /* For pending debug exceptions checks below. */
9672
9673 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9674 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
9675 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
9676 {
9677 if ( (u32Eflags & X86_EFL_TF)
9678 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9679 {
9680 /* Bit 14 is PendingDebug.BS. */
9681 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
9682 }
9683 if ( !(u32Eflags & X86_EFL_TF)
9684 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
9685 {
9686 /* Bit 14 is PendingDebug.BS. */
9687 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
9688 }
9689 }
9690
9691 /* VMCS link pointer. */
9692 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
9693 AssertRC(rc);
9694 if (u64Val != UINT64_C(0xffffffffffffffff))
9695 {
9696 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
9697 /** @todo Bits beyond the processor's physical-address width MBZ. */
9698 /** @todo SMM checks. */
9699 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
9700 Assert(pVmcsInfo->pvShadowVmcs);
9701 VMXVMCSREVID VmcsRevId;
9702 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
9703 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
9704 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
9705 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
9706 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
9707 }
9708
9709 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
9710 * not using nested paging? */
9711 if ( pVM->hm.s.fNestedPaging
9712 && !fLongModeGuest
9713 && CPUMIsGuestInPAEModeEx(pCtx))
9714 {
9715 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
9716 AssertRC(rc);
9717 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9718
9719 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
9720 AssertRC(rc);
9721 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9722
9723 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
9724 AssertRC(rc);
9725 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9726
9727 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
9728 AssertRC(rc);
9729 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
9730 }
9731
9732 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
9733 if (uError == VMX_IGS_ERROR)
9734 uError = VMX_IGS_REASON_NOT_FOUND;
9735 } while (0);
9736
9737 pVCpu->hm.s.u32HMError = uError;
9738 return uError;
9739
9740#undef HMVMX_ERROR_BREAK
9741#undef HMVMX_CHECK_BREAK
9742}
9743
9744
9745/**
9746 * Map the APIC-access page for virtualizing APIC accesses.
9747 *
9748 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
9749 * this not done as part of exporting guest state, see @bugref{8721}.
9750 *
9751 * @returns VBox status code.
9752 * @param pVCpu The cross context virtual CPU structure.
9753 */
9754static int hmR0VmxMapHCApicAccessPage(PVMCPUCC pVCpu)
9755{
9756 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9757 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
9758
9759 Assert(PDMHasApic(pVM));
9760 Assert(u64MsrApicBase);
9761
9762 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
9763 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
9764
9765 /* Unalias the existing mapping. */
9766 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
9767 AssertRCReturn(rc, rc);
9768
9769 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
9770 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
9771 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
9772 AssertRCReturn(rc, rc);
9773
9774 /* Update the per-VCPU cache of the APIC base MSR. */
9775 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
9776 return VINF_SUCCESS;
9777}
9778
9779
9780/**
9781 * Worker function passed to RTMpOnSpecific() that is to be called on the target
9782 * CPU.
9783 *
9784 * @param idCpu The ID for the CPU the function is called on.
9785 * @param pvUser1 Null, not used.
9786 * @param pvUser2 Null, not used.
9787 */
9788static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
9789{
9790 RT_NOREF3(idCpu, pvUser1, pvUser2);
9791 VMXDispatchHostNmi();
9792}
9793
9794
9795/**
9796 * Dispatching an NMI on the host CPU that received it.
9797 *
9798 * @returns VBox status code.
9799 * @param pVCpu The cross context virtual CPU structure.
9800 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
9801 * executing when receiving the host NMI in VMX non-root
9802 * operation.
9803 */
9804static int hmR0VmxExitHostNmi(PVMCPUCC pVCpu, PCVMXVMCSINFO pVmcsInfo)
9805{
9806 RTCPUID const idCpu = pVmcsInfo->idHostCpuExec;
9807 Assert(idCpu != NIL_RTCPUID);
9808
9809 /*
9810 * We don't want to delay dispatching the NMI any more than we have to. However,
9811 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
9812 * after executing guest or nested-guest code for the following reasons:
9813 *
9814 * - We would need to perform VMREADs with interrupts disabled and is orders of
9815 * magnitude worse when we run as a nested hypervisor without VMCS shadowing
9816 * supported by the host hypervisor.
9817 *
9818 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
9819 * longer period of time just for handling an edge case like host NMIs which do
9820 * not occur nearly as frequently as other VM-exits.
9821 *
9822 * Let's cover the most likely scenario first. Check if we are on the target CPU
9823 * and dispatch the NMI right away. This should be much faster than calling into
9824 * RTMpOnSpecific() machinery.
9825 */
9826 bool fDispatched = false;
9827 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
9828 if (idCpu == RTMpCpuId())
9829 {
9830 VMXDispatchHostNmi();
9831 fDispatched = true;
9832 }
9833 ASMSetFlags(fEFlags);
9834 if (fDispatched)
9835 {
9836 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
9837 return VINF_SUCCESS;
9838 }
9839
9840 /*
9841 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
9842 * there should be no race or recursion even if we are unlucky enough to be preempted
9843 * (to the target CPU) without dispatching the host NMI above.
9844 */
9845 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
9846 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
9847}
9848
9849
9850#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9851/**
9852 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
9853 * nested-guest using hardware-assisted VMX.
9854 *
9855 * @param pVCpu The cross context virtual CPU structure.
9856 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
9857 * @param pVmcsInfoGst The guest VMCS info. object.
9858 */
9859static void hmR0VmxMergeMsrBitmapNested(PCVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
9860{
9861 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
9862 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
9863 Assert(pu64MsrBitmap);
9864
9865 /*
9866 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
9867 * MSR that is intercepted by the guest is also intercepted while executing the
9868 * nested-guest using hardware-assisted VMX.
9869 *
9870 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
9871 * nested-guest VM-exit even if the outer guest is not intercepting some
9872 * MSRs. We cannot assume the caller has initialized the nested-guest
9873 * MSR bitmap in this case.
9874 *
9875 * The nested hypervisor may also switch whether it uses MSR bitmaps for
9876 * each VM-entry, hence initializing it once per-VM while setting up the
9877 * nested-guest VMCS is not sufficient.
9878 */
9879 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9880 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
9881 {
9882 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
9883 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
9884 Assert(pu64MsrBitmapNstGst);
9885 Assert(pu64MsrBitmapGst);
9886
9887 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
9888 for (uint32_t i = 0; i < cFrags; i++)
9889 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
9890 }
9891 else
9892 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
9893}
9894
9895
9896/**
9897 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
9898 * hardware-assisted VMX execution of the nested-guest.
9899 *
9900 * For a guest, we don't modify these controls once we set up the VMCS and hence
9901 * this function is never called.
9902 *
9903 * For nested-guests since the nested hypervisor provides these controls on every
9904 * nested-guest VM-entry and could potentially change them everytime we need to
9905 * merge them before every nested-guest VM-entry.
9906 *
9907 * @returns VBox status code.
9908 * @param pVCpu The cross context virtual CPU structure.
9909 */
9910static int hmR0VmxMergeVmcsNested(PVMCPUCC pVCpu)
9911{
9912 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
9913 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
9914 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
9915 Assert(pVmcsNstGst);
9916
9917 /*
9918 * Merge the controls with the requirements of the guest VMCS.
9919 *
9920 * We do not need to validate the nested-guest VMX features specified in the nested-guest
9921 * VMCS with the features supported by the physical CPU as it's already done by the
9922 * VMLAUNCH/VMRESUME instruction emulation.
9923 *
9924 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
9925 * derived from the VMX features supported by the physical CPU.
9926 */
9927
9928 /* Pin-based VM-execution controls. */
9929 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
9930
9931 /* Processor-based VM-execution controls. */
9932 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
9933 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
9934 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
9935 | VMX_PROC_CTLS_USE_TPR_SHADOW
9936 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
9937
9938 /* Secondary processor-based VM-execution controls. */
9939 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
9940 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
9941 | VMX_PROC_CTLS2_INVPCID
9942 | VMX_PROC_CTLS2_VMCS_SHADOWING
9943 | VMX_PROC_CTLS2_RDTSCP
9944 | VMX_PROC_CTLS2_XSAVES_XRSTORS
9945 | VMX_PROC_CTLS2_APIC_REG_VIRT
9946 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
9947 | VMX_PROC_CTLS2_VMFUNC));
9948
9949 /*
9950 * VM-entry controls:
9951 * These controls contains state that depends on the nested-guest state (primarily
9952 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
9953 * VM-exit. Although the nested hypervisor cannot change it, we need to in order to
9954 * properly continue executing the nested-guest if the EFER MSR changes but does not
9955 * cause a nested-guest VM-exits.
9956 *
9957 * VM-exit controls:
9958 * These controls specify the host state on return. We cannot use the controls from
9959 * the nested hypervisor state as is as it would contain the guest state rather than
9960 * the host state. Since the host state is subject to change (e.g. preemption, trips
9961 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
9962 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
9963 *
9964 * VM-entry MSR-load:
9965 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
9966 * context by the VMLAUNCH/VMRESUME instruction emulation.
9967 *
9968 * VM-exit MSR-store:
9969 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
9970 * back into the VM-exit MSR-store area.
9971 *
9972 * VM-exit MSR-load areas:
9973 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
9974 * can entirely ignore what the nested hypervisor wants to load here.
9975 */
9976
9977 /*
9978 * Exception bitmap.
9979 *
9980 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
9981 * here (and avoid doing anything while exporting nested-guest state), but to keep the
9982 * code more flexible if intercepting exceptions become more dynamic in the future we do
9983 * it as part of exporting the nested-guest state.
9984 */
9985 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
9986
9987 /*
9988 * CR0/CR4 guest/host mask.
9989 *
9990 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
9991 * cause VM-exits, so we need to merge them here.
9992 */
9993 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
9994 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
9995
9996 /*
9997 * Page-fault error-code mask and match.
9998 *
9999 * Although we require unrestricted guest execution (and thereby nested-paging) for
10000 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10001 * normally intercept #PFs, it might intercept them for debugging purposes.
10002 *
10003 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10004 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10005 */
10006 uint32_t u32XcptPFMask;
10007 uint32_t u32XcptPFMatch;
10008 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10009 {
10010 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10011 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10012 }
10013 else
10014 {
10015 u32XcptPFMask = 0;
10016 u32XcptPFMatch = 0;
10017 }
10018
10019 /*
10020 * Pause-Loop exiting.
10021 */
10022 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10023 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10024
10025 /*
10026 * Pending debug exceptions.
10027 * Currently just copy whatever the nested-guest provides us.
10028 */
10029 uint64_t const uPendingDbgXcpts = pVmcsNstGst->u64GuestPendingDbgXcpts.u;
10030
10031 /*
10032 * I/O Bitmap.
10033 *
10034 * We do not use the I/O bitmap that may be provided by the nested hypervisor as we always
10035 * intercept all I/O port accesses.
10036 */
10037 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10038 Assert(!(u32ProcCtls & VMX_PROC_CTLS_USE_IO_BITMAPS));
10039
10040 /*
10041 * VMCS shadowing.
10042 *
10043 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10044 * enabled while executing the nested-guest.
10045 */
10046 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10047
10048 /*
10049 * APIC-access page.
10050 */
10051 RTHCPHYS HCPhysApicAccess;
10052 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10053 {
10054 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS);
10055 RTGCPHYS const GCPhysApicAccess = pVmcsNstGst->u64AddrApicAccess.u;
10056
10057 /** @todo NSTVMX: This is not really correct but currently is required to make
10058 * things work. We need to re-enable the page handler when we fallback to
10059 * IEM execution of the nested-guest! */
10060 PGMHandlerPhysicalPageTempOff(pVM, GCPhysApicAccess, GCPhysApicAccess);
10061
10062 void *pvPage;
10063 PGMPAGEMAPLOCK PgLockApicAccess;
10064 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysApicAccess, &pvPage, &PgLockApicAccess);
10065 if (RT_SUCCESS(rc))
10066 {
10067 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysApicAccess, &HCPhysApicAccess);
10068 AssertMsgRCReturn(rc, ("Failed to get host-physical address for APIC-access page at %#RGp\n", GCPhysApicAccess), rc);
10069
10070 /** @todo Handle proper releasing of page-mapping lock later. */
10071 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockApicAccess);
10072 }
10073 else
10074 return rc;
10075 }
10076 else
10077 HCPhysApicAccess = 0;
10078
10079 /*
10080 * Virtual-APIC page and TPR threshold.
10081 */
10082 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10083 RTHCPHYS HCPhysVirtApic;
10084 uint32_t u32TprThreshold;
10085 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10086 {
10087 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW);
10088 RTGCPHYS const GCPhysVirtApic = pVmcsNstGst->u64AddrVirtApic.u;
10089
10090 void *pvPage;
10091 PGMPAGEMAPLOCK PgLockVirtApic;
10092 int rc = PGMPhysGCPhys2CCPtr(pVM, GCPhysVirtApic, &pvPage, &PgLockVirtApic);
10093 if (RT_SUCCESS(rc))
10094 {
10095 rc = PGMPhysGCPhys2HCPhys(pVM, GCPhysVirtApic, &HCPhysVirtApic);
10096 AssertMsgRCReturn(rc, ("Failed to get host-physical address for virtual-APIC page at %#RGp\n", GCPhysVirtApic), rc);
10097
10098 /** @todo Handle proper releasing of page-mapping lock later. */
10099 PGMPhysReleasePageMappingLock(pVCpu->CTX_SUFF(pVM), &PgLockVirtApic);
10100 }
10101 else
10102 return rc;
10103
10104 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10105 }
10106 else
10107 {
10108 HCPhysVirtApic = 0;
10109 u32TprThreshold = 0;
10110
10111 /*
10112 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10113 * used by the nested hypervisor. Preventing MMIO accesses to the physical APIC will
10114 * be taken care of by EPT/shadow paging.
10115 */
10116 if (pVM->hm.s.fAllow64BitGuests)
10117 {
10118 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10119 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10120 }
10121 }
10122
10123 /*
10124 * Validate basic assumptions.
10125 */
10126 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10127 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10128 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10129
10130 /*
10131 * Commit it to the nested-guest VMCS.
10132 */
10133 int rc = VINF_SUCCESS;
10134 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10135 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10136 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10137 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10138 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10139 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10140 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10141 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10142 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10143 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10144 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10145 rc |= VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10146 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10147 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10148 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10149 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10150 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10151 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10152 {
10153 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10154 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10155 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10156 }
10157 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10158 {
10159 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10160 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
10161 }
10162 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10163 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
10164 rc |= VMXWriteVmcsNw(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, uPendingDbgXcpts);
10165 AssertRC(rc);
10166
10167 /*
10168 * Update the nested-guest VMCS cache.
10169 */
10170 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10171 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10172 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10173 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10174 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10175 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10176 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10177 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10178 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10179
10180 /*
10181 * We need to flush the TLB if we are switching the APIC-access page address.
10182 * See Intel spec. 28.3.3.4 "Guidelines for Use of the INVEPT Instruction".
10183 */
10184 if (u32ProcCtls2 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10185 pVCpu->hm.s.vmx.fSwitchedNstGstFlushTlb = true;
10186
10187 /*
10188 * MSR bitmap.
10189 *
10190 * The MSR bitmap address has already been initialized while setting up the nested-guest
10191 * VMCS, here we need to merge the MSR bitmaps.
10192 */
10193 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10194 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10195
10196 return VINF_SUCCESS;
10197}
10198#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10199
10200
10201/**
10202 * Does the preparations before executing guest code in VT-x.
10203 *
10204 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10205 * recompiler/IEM. We must be cautious what we do here regarding committing
10206 * guest-state information into the VMCS assuming we assuredly execute the
10207 * guest in VT-x mode.
10208 *
10209 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10210 * the common-state (TRPM/forceflags), we must undo those changes so that the
10211 * recompiler/IEM can (and should) use them when it resumes guest execution.
10212 * Otherwise such operations must be done when we can no longer exit to ring-3.
10213 *
10214 * @returns Strict VBox status code (i.e. informational status codes too).
10215 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10216 * have been disabled.
10217 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10218 * pending events).
10219 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10220 * double-fault into the guest.
10221 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10222 * dispatched directly.
10223 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10224 *
10225 * @param pVCpu The cross context virtual CPU structure.
10226 * @param pVmxTransient The VMX-transient structure.
10227 * @param fStepping Whether we are single-stepping the guest in the
10228 * hypervisor debugger. Makes us ignore some of the reasons
10229 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
10230 * if event dispatching took place.
10231 */
10232static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
10233{
10234 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10235
10236 Log4Func(("fIsNested=%RTbool fStepping=%RTbool\n", pVmxTransient->fIsNestedGuest, fStepping));
10237
10238#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
10239 if (pVmxTransient->fIsNestedGuest)
10240 {
10241 RT_NOREF2(pVCpu, fStepping);
10242 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
10243 return VINF_EM_RESCHEDULE_REM;
10244 }
10245#endif
10246
10247#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
10248 PGMRZDynMapFlushAutoSet(pVCpu);
10249#endif
10250
10251 /*
10252 * Check and process force flag actions, some of which might require us to go back to ring-3.
10253 */
10254 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
10255 if (rcStrict == VINF_SUCCESS)
10256 {
10257 /* FFs don't get set all the time. */
10258#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10259 if ( pVmxTransient->fIsNestedGuest
10260 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10261 {
10262 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10263 return VINF_VMX_VMEXIT;
10264 }
10265#endif
10266 }
10267 else
10268 return rcStrict;
10269
10270 /*
10271 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
10272 */
10273 /** @todo Doing this from ring-3 after VM setup phase causes a
10274 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
10275 * idea why atm. */
10276 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10277 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
10278 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
10279 && PDMHasApic(pVM))
10280 {
10281 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
10282 AssertRCReturn(rc, rc);
10283 }
10284
10285#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10286 /*
10287 * Merge guest VMCS controls with the nested-guest VMCS controls.
10288 *
10289 * Even if we have not executed the guest prior to this (e.g. when resuming from a
10290 * saved state), we should be okay with merging controls as we initialize the
10291 * guest VMCS controls as part of VM setup phase.
10292 */
10293 if ( pVmxTransient->fIsNestedGuest
10294 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
10295 {
10296 int rc = hmR0VmxMergeVmcsNested(pVCpu);
10297 AssertRCReturn(rc, rc);
10298 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
10299 }
10300#endif
10301
10302 /*
10303 * Evaluate events to be injected into the guest.
10304 *
10305 * Events in TRPM can be injected without inspecting the guest state.
10306 * If any new events (interrupts/NMI) are pending currently, we try to set up the
10307 * guest to cause a VM-exit the next time they are ready to receive the event.
10308 *
10309 * With nested-guests, evaluating pending events may cause VM-exits. Also, verify
10310 * that the event in TRPM that we will inject using hardware-assisted VMX is -not-
10311 * subject to interecption. Otherwise, we should have checked and injected them
10312 * manually elsewhere (IEM).
10313 */
10314 if (TRPMHasTrap(pVCpu))
10315 {
10316 Assert(!pVmxTransient->fIsNestedGuest || !CPUMIsGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx));
10317 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
10318 }
10319
10320 uint32_t fIntrState;
10321 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
10322
10323#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10324 /*
10325 * While evaluating pending events if something failed (unlikely) or if we were
10326 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
10327 */
10328 if (rcStrict != VINF_SUCCESS)
10329 return rcStrict;
10330 if ( pVmxTransient->fIsNestedGuest
10331 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
10332 {
10333 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
10334 return VINF_VMX_VMEXIT;
10335 }
10336#else
10337 Assert(rcStrict == VINF_SUCCESS);
10338#endif
10339
10340 /*
10341 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
10342 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
10343 * also result in triple-faulting the VM.
10344 *
10345 * With nested-guests, the above does not apply since unrestricted guest execution is a
10346 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
10347 */
10348 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
10349 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10350 { /* likely */ }
10351 else
10352 {
10353 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
10354 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
10355 return rcStrict;
10356 }
10357
10358 /*
10359 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
10360 * import CR3 themselves. We will need to update them here, as even as late as the above
10361 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
10362 * the below force flags to be set.
10363 */
10364 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
10365 {
10366 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
10367 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
10368 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
10369 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
10370 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10371 }
10372 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
10373 {
10374 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
10375 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10376 }
10377
10378#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10379 /* Paranoia. */
10380 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10381#endif
10382
10383 /*
10384 * No longjmps to ring-3 from this point on!!!
10385 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
10386 * This also disables flushing of the R0-logger instance (if any).
10387 */
10388 VMMRZCallRing3Disable(pVCpu);
10389
10390 /*
10391 * Export the guest state bits.
10392 *
10393 * We cannot perform longjmps while loading the guest state because we do not preserve the
10394 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
10395 * CPU migration.
10396 *
10397 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
10398 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
10399 */
10400 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
10401 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
10402 { /* likely */ }
10403 else
10404 {
10405 VMMRZCallRing3Enable(pVCpu);
10406 return rcStrict;
10407 }
10408
10409 /*
10410 * We disable interrupts so that we don't miss any interrupts that would flag preemption
10411 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
10412 * preemption disabled for a while. Since this is purely to aid the
10413 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
10414 * disable interrupt on NT.
10415 *
10416 * We need to check for force-flags that could've possible been altered since we last
10417 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
10418 * see @bugref{6398}).
10419 *
10420 * We also check a couple of other force-flags as a last opportunity to get the EMT back
10421 * to ring-3 before executing guest code.
10422 */
10423 pVmxTransient->fEFlags = ASMIntDisableFlags();
10424
10425 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
10426 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
10427 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
10428 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
10429 {
10430 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
10431 {
10432#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10433 /*
10434 * If we are executing a nested-guest make sure that we should intercept subsequent
10435 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
10436 * the VM-exit instruction emulation happy.
10437 */
10438 if (pVmxTransient->fIsNestedGuest)
10439 CPUMSetGuestVmxInterceptEvents(&pVCpu->cpum.GstCtx, true);
10440#endif
10441
10442 /*
10443 * We've injected any pending events. This is really the point of no return (to ring-3).
10444 *
10445 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
10446 * returns from this function, so do -not- enable them here.
10447 */
10448 pVCpu->hm.s.Event.fPending = false;
10449 return VINF_SUCCESS;
10450 }
10451
10452 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
10453 rcStrict = VINF_EM_RAW_INTERRUPT;
10454 }
10455 else
10456 {
10457 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
10458 rcStrict = VINF_EM_RAW_TO_R3;
10459 }
10460
10461 ASMSetFlags(pVmxTransient->fEFlags);
10462 VMMRZCallRing3Enable(pVCpu);
10463
10464 return rcStrict;
10465}
10466
10467
10468/**
10469 * Final preparations before executing guest code using hardware-assisted VMX.
10470 *
10471 * We can no longer get preempted to a different host CPU and there are no returns
10472 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
10473 * failures), this function is not intended to fail sans unrecoverable hardware
10474 * errors.
10475 *
10476 * @param pVCpu The cross context virtual CPU structure.
10477 * @param pVmxTransient The VMX-transient structure.
10478 *
10479 * @remarks Called with preemption disabled.
10480 * @remarks No-long-jump zone!!!
10481 */
10482static void hmR0VmxPreRunGuestCommitted(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
10483{
10484 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10485 Assert(VMMR0IsLogFlushDisabled(pVCpu));
10486 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
10487 Assert(!pVCpu->hm.s.Event.fPending);
10488
10489 /*
10490 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
10491 */
10492 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10493 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
10494
10495 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
10496 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10497 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
10498 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
10499
10500 if (!CPUMIsGuestFPUStateActive(pVCpu))
10501 {
10502 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10503 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
10504 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
10505 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
10506 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
10507 }
10508
10509 /*
10510 * Re-export the host state bits as we may've been preempted (only happens when
10511 * thread-context hooks are used or when the VM start function changes) or if
10512 * the host CR0 is modified while loading the guest FPU state above.
10513 *
10514 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
10515 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
10516 * see @bugref{8432}.
10517 *
10518 * This may also happen when switching to/from a nested-guest VMCS without leaving
10519 * ring-0.
10520 */
10521 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
10522 {
10523 hmR0VmxExportHostState(pVCpu);
10524 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
10525 }
10526 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
10527
10528 /*
10529 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
10530 */
10531 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
10532 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
10533 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
10534
10535 /*
10536 * Store status of the shared guest/host debug state at the time of VM-entry.
10537 */
10538 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
10539 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
10540
10541 /*
10542 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
10543 * more than one conditional check. The post-run side of our code shall determine
10544 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
10545 */
10546 if (pVmcsInfo->pbVirtApic)
10547 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
10548
10549 /*
10550 * Update the host MSRs values in the VM-exit MSR-load area.
10551 */
10552 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
10553 {
10554 if (pVmcsInfo->cExitMsrLoad > 0)
10555 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
10556 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
10557 }
10558
10559 /*
10560 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
10561 * VMX-preemption timer based on the next virtual sync clock deadline.
10562 */
10563 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
10564 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
10565 {
10566 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
10567 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
10568 }
10569
10570 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
10571 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
10572 if (!fIsRdtscIntercepted)
10573 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
10574 else
10575 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
10576
10577 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
10578 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
10579 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
10580 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Record the error reporting info. with the current host CPU. */
10581 pVmcsInfo->idHostCpuState = idCurrentCpu; /* Record the CPU for which the host-state has been exported. */
10582 pVmcsInfo->idHostCpuExec = idCurrentCpu; /* Record the CPU on which we shall execute. */
10583
10584 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
10585
10586 TMNotifyStartOfExecution(pVM, pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
10587 as we're about to start executing the guest. */
10588
10589 /*
10590 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
10591 *
10592 * This is done this late as updating the TSC offsetting/preemption timer above
10593 * figures out if we can skip intercepting RDTSCP by calculating the number of
10594 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
10595 */
10596 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
10597 && !fIsRdtscIntercepted)
10598 {
10599 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
10600
10601 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
10602 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
10603 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
10604 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
10605 AssertRC(rc);
10606 Assert(!pVmxTransient->fRemoveTscAuxMsr);
10607 pVmxTransient->fRemoveTscAuxMsr = true;
10608 }
10609
10610#ifdef VBOX_STRICT
10611 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
10612 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
10613 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
10614 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
10615#endif
10616
10617#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
10618 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
10619 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
10620 * see @bugref{9180#c54}. */
10621 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
10622 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
10623 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
10624#endif
10625}
10626
10627
10628/**
10629 * First C routine invoked after running guest code using hardware-assisted VMX.
10630 *
10631 * @param pVCpu The cross context virtual CPU structure.
10632 * @param pVmxTransient The VMX-transient structure.
10633 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
10634 *
10635 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
10636 *
10637 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
10638 * unconditionally when it is safe to do so.
10639 */
10640static void hmR0VmxPostRunGuest(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
10641{
10642 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
10643
10644 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
10645 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
10646 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
10647 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
10648 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
10649 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
10650
10651 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
10652 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
10653 {
10654 uint64_t uGstTsc;
10655 if (!pVmxTransient->fIsNestedGuest)
10656 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10657 else
10658 {
10659 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
10660 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
10661 }
10662 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
10663 }
10664
10665 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
10666 TMNotifyEndOfExecution(pVCpu->CTX_SUFF(pVM), pVCpu); /* Notify TM that the guest is no longer running. */
10667 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
10668
10669 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
10670 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
10671#ifdef VBOX_STRICT
10672 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
10673#endif
10674 Assert(!ASMIntAreEnabled());
10675 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
10676 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
10677
10678#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
10679 /*
10680 * Clean all the VMCS fields in the transient structure before reading
10681 * anything from the VMCS.
10682 */
10683 pVmxTransient->uExitReason = 0;
10684 pVmxTransient->uExitIntErrorCode = 0;
10685 pVmxTransient->uExitQual = 0;
10686 pVmxTransient->uGuestLinearAddr = 0;
10687 pVmxTransient->uExitIntInfo = 0;
10688 pVmxTransient->cbExitInstr = 0;
10689 pVmxTransient->ExitInstrInfo.u = 0;
10690 pVmxTransient->uEntryIntInfo = 0;
10691 pVmxTransient->uEntryXcptErrorCode = 0;
10692 pVmxTransient->cbEntryInstr = 0;
10693 pVmxTransient->uIdtVectoringInfo = 0;
10694 pVmxTransient->uIdtVectoringErrorCode = 0;
10695#endif
10696
10697 /*
10698 * Save the basic VM-exit reason and check if the VM-entry failed.
10699 * See Intel spec. 24.9.1 "Basic VM-exit Information".
10700 */
10701 uint32_t uExitReason;
10702 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
10703 AssertRC(rc);
10704 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
10705 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
10706
10707 /*
10708 * Log the VM-exit before logging anything else as otherwise it might be a
10709 * tad confusing what happens before and after the world-switch.
10710 */
10711 HMVMX_LOG_EXIT(pVCpu, uExitReason);
10712
10713 /*
10714 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
10715 * bitmap permissions, if it was added before VM-entry.
10716 */
10717 if (pVmxTransient->fRemoveTscAuxMsr)
10718 {
10719 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
10720 pVmxTransient->fRemoveTscAuxMsr = false;
10721 }
10722
10723 /*
10724 * Check if VMLAUNCH/VMRESUME succeeded.
10725 * If this failed, we cause a guru meditation and cease further execution.
10726 *
10727 * However, if we are executing a nested-guest we might fail if we use the
10728 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
10729 */
10730 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
10731 {
10732 /*
10733 * Update the VM-exit history array here even if the VM-entry failed due to:
10734 * - Invalid guest state.
10735 * - MSR loading.
10736 * - Machine-check event.
10737 *
10738 * In any of the above cases we will still have a "valid" VM-exit reason
10739 * despite @a fVMEntryFailed being false.
10740 *
10741 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
10742 *
10743 * Note! We don't have CS or RIP at this point. Will probably address that later
10744 * by amending the history entry added here.
10745 */
10746 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
10747 UINT64_MAX, uHostTsc);
10748
10749 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
10750 {
10751 VMMRZCallRing3Enable(pVCpu);
10752
10753 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
10754 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
10755
10756#ifdef HMVMX_ALWAYS_SAVE_RO_GUEST_STATE
10757 hmR0VmxReadAllRoFieldsVmcs(pVmxTransient);
10758#endif
10759#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
10760 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
10761 AssertRC(rc);
10762#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
10763 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
10764 AssertRC(rc);
10765#else
10766 /*
10767 * Import the guest-interruptibility state always as we need it while evaluating
10768 * injecting events on re-entry.
10769 *
10770 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
10771 * checking for real-mode while exporting the state because all bits that cause
10772 * mode changes wrt CR0 are intercepted.
10773 */
10774 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
10775 AssertRC(rc);
10776#endif
10777
10778 /*
10779 * Sync the TPR shadow with our APIC state.
10780 */
10781 if ( !pVmxTransient->fIsNestedGuest
10782 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
10783 {
10784 Assert(pVmcsInfo->pbVirtApic);
10785 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
10786 {
10787 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
10788 AssertRC(rc);
10789 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
10790 }
10791 }
10792
10793 Assert(VMMRZCallRing3IsEnabled(pVCpu));
10794 return;
10795 }
10796 }
10797#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10798 else if (pVmxTransient->fIsNestedGuest)
10799 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
10800#endif
10801 else
10802 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
10803
10804 VMMRZCallRing3Enable(pVCpu);
10805}
10806
10807
10808/**
10809 * Runs the guest code using hardware-assisted VMX the normal way.
10810 *
10811 * @returns VBox status code.
10812 * @param pVCpu The cross context virtual CPU structure.
10813 * @param pcLoops Pointer to the number of executed loops.
10814 */
10815static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPUCC pVCpu, uint32_t *pcLoops)
10816{
10817 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10818 Assert(pcLoops);
10819 Assert(*pcLoops <= cMaxResumeLoops);
10820 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10821
10822#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10823 /*
10824 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
10825 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
10826 * guest VMCS while entering the VMX ring-0 session.
10827 */
10828 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10829 {
10830 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
10831 if (RT_SUCCESS(rc))
10832 { /* likely */ }
10833 else
10834 {
10835 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
10836 return rc;
10837 }
10838 }
10839#endif
10840
10841 VMXTRANSIENT VmxTransient;
10842 RT_ZERO(VmxTransient);
10843 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10844
10845 /* Paranoia. */
10846 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
10847
10848 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10849 for (;;)
10850 {
10851 Assert(!HMR0SuspendPending());
10852 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10853 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10854
10855 /*
10856 * Preparatory work for running nested-guest code, this may force us to
10857 * return to ring-3.
10858 *
10859 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10860 */
10861 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10862 if (rcStrict != VINF_SUCCESS)
10863 break;
10864
10865 /* Interrupts are disabled at this point! */
10866 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10867 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10868 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10869 /* Interrupts are re-enabled at this point! */
10870
10871 /*
10872 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10873 */
10874 if (RT_SUCCESS(rcRun))
10875 { /* very likely */ }
10876 else
10877 {
10878 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10879 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10880 return rcRun;
10881 }
10882
10883 /*
10884 * Profile the VM-exit.
10885 */
10886 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10887 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
10888 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
10889 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
10890 HMVMX_START_EXIT_DISPATCH_PROF();
10891
10892 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
10893
10894 /*
10895 * Handle the VM-exit.
10896 */
10897#ifdef HMVMX_USE_FUNCTION_TABLE
10898 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
10899#else
10900 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
10901#endif
10902 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
10903 if (rcStrict == VINF_SUCCESS)
10904 {
10905 if (++(*pcLoops) <= cMaxResumeLoops)
10906 continue;
10907 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
10908 rcStrict = VINF_EM_RAW_INTERRUPT;
10909 }
10910 break;
10911 }
10912
10913 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
10914 return rcStrict;
10915}
10916
10917
10918#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10919/**
10920 * Runs the nested-guest code using hardware-assisted VMX.
10921 *
10922 * @returns VBox status code.
10923 * @param pVCpu The cross context virtual CPU structure.
10924 * @param pcLoops Pointer to the number of executed loops.
10925 *
10926 * @sa hmR0VmxRunGuestCodeNormal.
10927 */
10928static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPUCC pVCpu, uint32_t *pcLoops)
10929{
10930 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
10931 Assert(pcLoops);
10932 Assert(*pcLoops <= cMaxResumeLoops);
10933 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
10934
10935 /*
10936 * Switch to the nested-guest VMCS as we may have transitioned from executing the
10937 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
10938 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
10939 */
10940 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
10941 {
10942 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
10943 if (RT_SUCCESS(rc))
10944 { /* likely */ }
10945 else
10946 {
10947 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
10948 return rc;
10949 }
10950 }
10951
10952 VMXTRANSIENT VmxTransient;
10953 RT_ZERO(VmxTransient);
10954 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
10955 VmxTransient.fIsNestedGuest = true;
10956
10957 /* Paranoia. */
10958 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
10959
10960 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
10961 for (;;)
10962 {
10963 Assert(!HMR0SuspendPending());
10964 HMVMX_ASSERT_CPU_SAFE(pVCpu);
10965 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
10966
10967 /*
10968 * Preparatory work for running guest code, this may force us to
10969 * return to ring-3.
10970 *
10971 * Warning! This bugger disables interrupts on VINF_SUCCESS!
10972 */
10973 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
10974 if (rcStrict != VINF_SUCCESS)
10975 break;
10976
10977 /* Interrupts are disabled at this point! */
10978 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
10979 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
10980 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
10981 /* Interrupts are re-enabled at this point! */
10982
10983 /*
10984 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
10985 */
10986 if (RT_SUCCESS(rcRun))
10987 { /* very likely */ }
10988 else
10989 {
10990 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
10991 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
10992 return rcRun;
10993 }
10994
10995 /*
10996 * Profile the VM-exit.
10997 */
10998 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
10999 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11000 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11001 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11002 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11003 HMVMX_START_EXIT_DISPATCH_PROF();
11004
11005 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11006
11007 /*
11008 * Handle the VM-exit.
11009 */
11010 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11011 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11012 if (rcStrict == VINF_SUCCESS)
11013 {
11014 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11015 {
11016 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11017 rcStrict = VINF_VMX_VMEXIT;
11018 }
11019 else
11020 {
11021 if (++(*pcLoops) <= cMaxResumeLoops)
11022 continue;
11023 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11024 rcStrict = VINF_EM_RAW_INTERRUPT;
11025 }
11026 }
11027 else
11028 Assert(rcStrict != VINF_VMX_VMEXIT);
11029 break;
11030 }
11031
11032 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11033 return rcStrict;
11034}
11035#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11036
11037
11038/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11039 * probes.
11040 *
11041 * The following few functions and associated structure contains the bloat
11042 * necessary for providing detailed debug events and dtrace probes as well as
11043 * reliable host side single stepping. This works on the principle of
11044 * "subclassing" the normal execution loop and workers. We replace the loop
11045 * method completely and override selected helpers to add necessary adjustments
11046 * to their core operation.
11047 *
11048 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11049 * any performance for debug and analysis features.
11050 *
11051 * @{
11052 */
11053
11054/**
11055 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11056 * the debug run loop.
11057 */
11058typedef struct VMXRUNDBGSTATE
11059{
11060 /** The RIP we started executing at. This is for detecting that we stepped. */
11061 uint64_t uRipStart;
11062 /** The CS we started executing with. */
11063 uint16_t uCsStart;
11064
11065 /** Whether we've actually modified the 1st execution control field. */
11066 bool fModifiedProcCtls : 1;
11067 /** Whether we've actually modified the 2nd execution control field. */
11068 bool fModifiedProcCtls2 : 1;
11069 /** Whether we've actually modified the exception bitmap. */
11070 bool fModifiedXcptBitmap : 1;
11071
11072 /** We desire the modified the CR0 mask to be cleared. */
11073 bool fClearCr0Mask : 1;
11074 /** We desire the modified the CR4 mask to be cleared. */
11075 bool fClearCr4Mask : 1;
11076 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11077 uint32_t fCpe1Extra;
11078 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11079 uint32_t fCpe1Unwanted;
11080 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11081 uint32_t fCpe2Extra;
11082 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11083 uint32_t bmXcptExtra;
11084 /** The sequence number of the Dtrace provider settings the state was
11085 * configured against. */
11086 uint32_t uDtraceSettingsSeqNo;
11087 /** VM-exits to check (one bit per VM-exit). */
11088 uint32_t bmExitsToCheck[3];
11089
11090 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11091 uint32_t fProcCtlsInitial;
11092 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11093 uint32_t fProcCtls2Initial;
11094 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11095 uint32_t bmXcptInitial;
11096} VMXRUNDBGSTATE;
11097AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11098typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11099
11100
11101/**
11102 * Initializes the VMXRUNDBGSTATE structure.
11103 *
11104 * @param pVCpu The cross context virtual CPU structure of the
11105 * calling EMT.
11106 * @param pVmxTransient The VMX-transient structure.
11107 * @param pDbgState The debug state to initialize.
11108 */
11109static void hmR0VmxRunDebugStateInit(PVMCPUCC pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11110{
11111 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11112 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11113
11114 pDbgState->fModifiedProcCtls = false;
11115 pDbgState->fModifiedProcCtls2 = false;
11116 pDbgState->fModifiedXcptBitmap = false;
11117 pDbgState->fClearCr0Mask = false;
11118 pDbgState->fClearCr4Mask = false;
11119 pDbgState->fCpe1Extra = 0;
11120 pDbgState->fCpe1Unwanted = 0;
11121 pDbgState->fCpe2Extra = 0;
11122 pDbgState->bmXcptExtra = 0;
11123 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11124 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11125 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11126}
11127
11128
11129/**
11130 * Updates the VMSC fields with changes requested by @a pDbgState.
11131 *
11132 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11133 * immediately before executing guest code, i.e. when interrupts are disabled.
11134 * We don't check status codes here as we cannot easily assert or return in the
11135 * latter case.
11136 *
11137 * @param pVCpu The cross context virtual CPU structure.
11138 * @param pVmxTransient The VMX-transient structure.
11139 * @param pDbgState The debug state.
11140 */
11141static void hmR0VmxPreRunGuestDebugStateApply(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11142{
11143 /*
11144 * Ensure desired flags in VMCS control fields are set.
11145 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11146 *
11147 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11148 * there should be no stale data in pCtx at this point.
11149 */
11150 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11151 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11152 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11153 {
11154 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11155 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11156 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11157 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11158 pDbgState->fModifiedProcCtls = true;
11159 }
11160
11161 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11162 {
11163 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11164 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11165 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11166 pDbgState->fModifiedProcCtls2 = true;
11167 }
11168
11169 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11170 {
11171 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11172 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11173 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11174 pDbgState->fModifiedXcptBitmap = true;
11175 }
11176
11177 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11178 {
11179 pVmcsInfo->u64Cr0Mask = 0;
11180 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR0_MASK, 0);
11181 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11182 }
11183
11184 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11185 {
11186 pVmcsInfo->u64Cr4Mask = 0;
11187 VMXWriteVmcsNw(VMX_VMCS_CTRL_CR4_MASK, 0);
11188 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11189 }
11190
11191 NOREF(pVCpu);
11192}
11193
11194
11195/**
11196 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11197 * re-entry next time around.
11198 *
11199 * @returns Strict VBox status code (i.e. informational status codes too).
11200 * @param pVCpu The cross context virtual CPU structure.
11201 * @param pVmxTransient The VMX-transient structure.
11202 * @param pDbgState The debug state.
11203 * @param rcStrict The return code from executing the guest using single
11204 * stepping.
11205 */
11206static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11207 VBOXSTRICTRC rcStrict)
11208{
11209 /*
11210 * Restore VM-exit control settings as we may not reenter this function the
11211 * next time around.
11212 */
11213 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11214
11215 /* We reload the initial value, trigger what we can of recalculations the
11216 next time around. From the looks of things, that's all that's required atm. */
11217 if (pDbgState->fModifiedProcCtls)
11218 {
11219 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11220 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11221 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
11222 AssertRC(rc2);
11223 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
11224 }
11225
11226 /* We're currently the only ones messing with this one, so just restore the
11227 cached value and reload the field. */
11228 if ( pDbgState->fModifiedProcCtls2
11229 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
11230 {
11231 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
11232 AssertRC(rc2);
11233 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
11234 }
11235
11236 /* If we've modified the exception bitmap, we restore it and trigger
11237 reloading and partial recalculation the next time around. */
11238 if (pDbgState->fModifiedXcptBitmap)
11239 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
11240
11241 return rcStrict;
11242}
11243
11244
11245/**
11246 * Configures VM-exit controls for current DBGF and DTrace settings.
11247 *
11248 * This updates @a pDbgState and the VMCS execution control fields to reflect
11249 * the necessary VM-exits demanded by DBGF and DTrace.
11250 *
11251 * @param pVCpu The cross context virtual CPU structure.
11252 * @param pVmxTransient The VMX-transient structure. May update
11253 * fUpdatedTscOffsettingAndPreemptTimer.
11254 * @param pDbgState The debug state.
11255 */
11256static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11257{
11258 /*
11259 * Take down the dtrace serial number so we can spot changes.
11260 */
11261 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
11262 ASMCompilerBarrier();
11263
11264 /*
11265 * We'll rebuild most of the middle block of data members (holding the
11266 * current settings) as we go along here, so start by clearing it all.
11267 */
11268 pDbgState->bmXcptExtra = 0;
11269 pDbgState->fCpe1Extra = 0;
11270 pDbgState->fCpe1Unwanted = 0;
11271 pDbgState->fCpe2Extra = 0;
11272 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
11273 pDbgState->bmExitsToCheck[i] = 0;
11274
11275 /*
11276 * Software interrupts (INT XXh) - no idea how to trigger these...
11277 */
11278 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11279 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
11280 || VBOXVMM_INT_SOFTWARE_ENABLED())
11281 {
11282 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11283 }
11284
11285 /*
11286 * INT3 breakpoints - triggered by #BP exceptions.
11287 */
11288 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
11289 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11290
11291 /*
11292 * Exception bitmap and XCPT events+probes.
11293 */
11294 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
11295 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
11296 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
11297
11298 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
11299 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
11300 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
11301 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
11302 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
11303 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
11304 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
11305 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
11306 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
11307 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
11308 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
11309 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
11310 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
11311 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
11312 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
11313 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
11314 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
11315 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
11316
11317 if (pDbgState->bmXcptExtra)
11318 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
11319
11320 /*
11321 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
11322 *
11323 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
11324 * So, when adding/changing/removing please don't forget to update it.
11325 *
11326 * Some of the macros are picking up local variables to save horizontal space,
11327 * (being able to see it in a table is the lesser evil here).
11328 */
11329#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
11330 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
11331 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
11332#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
11333 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11334 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11335 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11336 } else do { } while (0)
11337#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
11338 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11339 { \
11340 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
11341 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11342 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11343 } else do { } while (0)
11344#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
11345 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11346 { \
11347 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
11348 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11349 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11350 } else do { } while (0)
11351#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
11352 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
11353 { \
11354 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
11355 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
11356 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
11357 } else do { } while (0)
11358
11359 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
11360 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
11361 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
11362 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
11363 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
11364
11365 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
11366 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
11367 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
11368 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
11369 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
11370 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
11371 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
11372 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
11373 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
11374 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
11375 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
11376 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
11377 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
11378 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
11379 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
11380 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
11381 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
11382 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
11383 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
11384 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
11385 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
11386 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
11387 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
11388 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
11389 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
11390 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
11391 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
11392 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
11393 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
11394 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
11395 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
11396 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
11397 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
11398 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
11399 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
11400 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
11401
11402 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
11403 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11404 {
11405 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
11406 | CPUMCTX_EXTRN_APIC_TPR);
11407 AssertRC(rc);
11408
11409#if 0 /** @todo fix me */
11410 pDbgState->fClearCr0Mask = true;
11411 pDbgState->fClearCr4Mask = true;
11412#endif
11413 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
11414 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
11415 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
11416 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
11417 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
11418 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
11419 require clearing here and in the loop if we start using it. */
11420 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
11421 }
11422 else
11423 {
11424 if (pDbgState->fClearCr0Mask)
11425 {
11426 pDbgState->fClearCr0Mask = false;
11427 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
11428 }
11429 if (pDbgState->fClearCr4Mask)
11430 {
11431 pDbgState->fClearCr4Mask = false;
11432 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
11433 }
11434 }
11435 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
11436 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
11437
11438 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
11439 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
11440 {
11441 /** @todo later, need to fix handler as it assumes this won't usually happen. */
11442 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
11443 }
11444 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
11445 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
11446
11447 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
11448 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
11449 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
11450 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
11451 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
11452 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
11453 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
11454 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
11455#if 0 /** @todo too slow, fix handler. */
11456 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
11457#endif
11458 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
11459
11460 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
11461 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
11462 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
11463 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
11464 {
11465 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11466 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
11467 }
11468 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11469 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11470 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11471 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
11472
11473 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
11474 || IS_EITHER_ENABLED(pVM, INSTR_STR)
11475 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
11476 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
11477 {
11478 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
11479 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
11480 }
11481 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
11482 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
11483 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
11484 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
11485
11486 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
11487 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
11488 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
11489 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
11490 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
11491 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
11492 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
11493 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
11494 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
11495 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
11496 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
11497 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
11498 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
11499 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
11500 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
11501 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
11502 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
11503 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
11504 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
11505 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
11506 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
11507 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
11508
11509#undef IS_EITHER_ENABLED
11510#undef SET_ONLY_XBM_IF_EITHER_EN
11511#undef SET_CPE1_XBM_IF_EITHER_EN
11512#undef SET_CPEU_XBM_IF_EITHER_EN
11513#undef SET_CPE2_XBM_IF_EITHER_EN
11514
11515 /*
11516 * Sanitize the control stuff.
11517 */
11518 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
11519 if (pDbgState->fCpe2Extra)
11520 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
11521 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
11522 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
11523 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
11524 {
11525 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
11526 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
11527 }
11528
11529 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
11530 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
11531 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
11532 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
11533}
11534
11535
11536/**
11537 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
11538 * appropriate.
11539 *
11540 * The caller has checked the VM-exit against the
11541 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
11542 * already, so we don't have to do that either.
11543 *
11544 * @returns Strict VBox status code (i.e. informational status codes too).
11545 * @param pVCpu The cross context virtual CPU structure.
11546 * @param pVmxTransient The VMX-transient structure.
11547 * @param uExitReason The VM-exit reason.
11548 *
11549 * @remarks The name of this function is displayed by dtrace, so keep it short
11550 * and to the point. No longer than 33 chars long, please.
11551 */
11552static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
11553{
11554 /*
11555 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
11556 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
11557 *
11558 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
11559 * does. Must add/change/remove both places. Same ordering, please.
11560 *
11561 * Added/removed events must also be reflected in the next section
11562 * where we dispatch dtrace events.
11563 */
11564 bool fDtrace1 = false;
11565 bool fDtrace2 = false;
11566 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
11567 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
11568 uint32_t uEventArg = 0;
11569#define SET_EXIT(a_EventSubName) \
11570 do { \
11571 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11572 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11573 } while (0)
11574#define SET_BOTH(a_EventSubName) \
11575 do { \
11576 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
11577 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
11578 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
11579 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
11580 } while (0)
11581 switch (uExitReason)
11582 {
11583 case VMX_EXIT_MTF:
11584 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11585
11586 case VMX_EXIT_XCPT_OR_NMI:
11587 {
11588 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
11589 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
11590 {
11591 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
11592 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
11593 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
11594 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
11595 {
11596 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
11597 {
11598 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
11599 uEventArg = pVmxTransient->uExitIntErrorCode;
11600 }
11601 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
11602 switch (enmEvent1)
11603 {
11604 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
11605 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
11606 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
11607 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
11608 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
11609 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
11610 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
11611 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
11612 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
11613 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
11614 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
11615 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
11616 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
11617 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
11618 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
11619 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
11620 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
11621 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
11622 default: break;
11623 }
11624 }
11625 else
11626 AssertFailed();
11627 break;
11628
11629 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
11630 uEventArg = idxVector;
11631 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
11632 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
11633 break;
11634 }
11635 break;
11636 }
11637
11638 case VMX_EXIT_TRIPLE_FAULT:
11639 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
11640 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
11641 break;
11642 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
11643 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
11644 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
11645 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
11646 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
11647
11648 /* Instruction specific VM-exits: */
11649 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
11650 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
11651 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
11652 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
11653 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
11654 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
11655 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
11656 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
11657 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
11658 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
11659 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
11660 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
11661 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
11662 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
11663 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
11664 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
11665 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
11666 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
11667 case VMX_EXIT_MOV_CRX:
11668 hmR0VmxReadExitQualVmcs(pVmxTransient);
11669 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
11670 SET_BOTH(CRX_READ);
11671 else
11672 SET_BOTH(CRX_WRITE);
11673 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
11674 break;
11675 case VMX_EXIT_MOV_DRX:
11676 hmR0VmxReadExitQualVmcs(pVmxTransient);
11677 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
11678 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
11679 SET_BOTH(DRX_READ);
11680 else
11681 SET_BOTH(DRX_WRITE);
11682 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
11683 break;
11684 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
11685 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
11686 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
11687 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
11688 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
11689 case VMX_EXIT_GDTR_IDTR_ACCESS:
11690 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11691 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
11692 {
11693 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
11694 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
11695 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
11696 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
11697 }
11698 break;
11699
11700 case VMX_EXIT_LDTR_TR_ACCESS:
11701 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
11702 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
11703 {
11704 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
11705 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
11706 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
11707 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
11708 }
11709 break;
11710
11711 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
11712 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
11713 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
11714 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
11715 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
11716 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
11717 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
11718 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
11719 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
11720 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
11721 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
11722
11723 /* Events that aren't relevant at this point. */
11724 case VMX_EXIT_EXT_INT:
11725 case VMX_EXIT_INT_WINDOW:
11726 case VMX_EXIT_NMI_WINDOW:
11727 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11728 case VMX_EXIT_PREEMPT_TIMER:
11729 case VMX_EXIT_IO_INSTR:
11730 break;
11731
11732 /* Errors and unexpected events. */
11733 case VMX_EXIT_INIT_SIGNAL:
11734 case VMX_EXIT_SIPI:
11735 case VMX_EXIT_IO_SMI:
11736 case VMX_EXIT_SMI:
11737 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
11738 case VMX_EXIT_ERR_MSR_LOAD:
11739 case VMX_EXIT_ERR_MACHINE_CHECK:
11740 case VMX_EXIT_PML_FULL:
11741 case VMX_EXIT_VIRTUALIZED_EOI:
11742 break;
11743
11744 default:
11745 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
11746 break;
11747 }
11748#undef SET_BOTH
11749#undef SET_EXIT
11750
11751 /*
11752 * Dtrace tracepoints go first. We do them here at once so we don't
11753 * have to copy the guest state saving and stuff a few dozen times.
11754 * Down side is that we've got to repeat the switch, though this time
11755 * we use enmEvent since the probes are a subset of what DBGF does.
11756 */
11757 if (fDtrace1 || fDtrace2)
11758 {
11759 hmR0VmxReadExitQualVmcs(pVmxTransient);
11760 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11761 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
11762 switch (enmEvent1)
11763 {
11764 /** @todo consider which extra parameters would be helpful for each probe. */
11765 case DBGFEVENT_END: break;
11766 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
11767 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
11768 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
11769 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
11770 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
11771 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
11772 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
11773 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
11774 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
11775 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
11776 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
11777 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
11778 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
11779 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
11780 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
11781 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
11782 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
11783 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
11784 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11785 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11786 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
11787 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
11788 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
11789 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
11790 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
11791 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
11792 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
11793 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11794 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11795 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11796 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11797 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11798 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
11799 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11800 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
11801 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
11802 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
11803 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
11804 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
11805 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
11806 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
11807 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
11808 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
11809 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
11810 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
11811 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
11812 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
11813 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
11814 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
11815 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
11816 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
11817 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
11818 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
11819 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
11820 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
11821 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
11822 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
11823 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
11824 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
11825 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
11826 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
11827 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
11828 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
11829 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
11830 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
11831 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
11832 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
11833 }
11834 switch (enmEvent2)
11835 {
11836 /** @todo consider which extra parameters would be helpful for each probe. */
11837 case DBGFEVENT_END: break;
11838 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
11839 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
11840 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
11841 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
11842 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
11843 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
11844 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
11845 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
11846 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
11847 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11848 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11849 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
11850 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
11851 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
11852 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
11853 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
11854 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
11855 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
11856 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
11857 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
11858 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
11859 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
11860 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
11861 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
11862 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
11863 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
11864 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
11865 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
11866 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
11867 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
11868 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
11869 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
11870 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
11871 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
11872 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
11873 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
11874 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
11875 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
11876 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
11877 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
11878 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
11879 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
11880 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
11881 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
11882 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
11883 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
11884 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
11885 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
11886 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
11887 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
11888 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
11889 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
11890 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
11891 }
11892 }
11893
11894 /*
11895 * Fire of the DBGF event, if enabled (our check here is just a quick one,
11896 * the DBGF call will do a full check).
11897 *
11898 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
11899 * Note! If we have to events, we prioritize the first, i.e. the instruction
11900 * one, in order to avoid event nesting.
11901 */
11902 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
11903 if ( enmEvent1 != DBGFEVENT_END
11904 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
11905 {
11906 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11907 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
11908 if (rcStrict != VINF_SUCCESS)
11909 return rcStrict;
11910 }
11911 else if ( enmEvent2 != DBGFEVENT_END
11912 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
11913 {
11914 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
11915 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
11916 if (rcStrict != VINF_SUCCESS)
11917 return rcStrict;
11918 }
11919
11920 return VINF_SUCCESS;
11921}
11922
11923
11924/**
11925 * Single-stepping VM-exit filtering.
11926 *
11927 * This is preprocessing the VM-exits and deciding whether we've gotten far
11928 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
11929 * handling is performed.
11930 *
11931 * @returns Strict VBox status code (i.e. informational status codes too).
11932 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
11933 * @param pVmxTransient The VMX-transient structure.
11934 * @param pDbgState The debug state.
11935 */
11936DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11937{
11938 /*
11939 * Expensive (saves context) generic dtrace VM-exit probe.
11940 */
11941 uint32_t const uExitReason = pVmxTransient->uExitReason;
11942 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
11943 { /* more likely */ }
11944 else
11945 {
11946 hmR0VmxReadExitQualVmcs(pVmxTransient);
11947 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11948 AssertRC(rc);
11949 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
11950 }
11951
11952 /*
11953 * Check for host NMI, just to get that out of the way.
11954 */
11955 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
11956 { /* normally likely */ }
11957 else
11958 {
11959 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
11960 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
11961 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
11962 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
11963 }
11964
11965 /*
11966 * Check for single stepping event if we're stepping.
11967 */
11968 if (pVCpu->hm.s.fSingleInstruction)
11969 {
11970 switch (uExitReason)
11971 {
11972 case VMX_EXIT_MTF:
11973 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
11974
11975 /* Various events: */
11976 case VMX_EXIT_XCPT_OR_NMI:
11977 case VMX_EXIT_EXT_INT:
11978 case VMX_EXIT_TRIPLE_FAULT:
11979 case VMX_EXIT_INT_WINDOW:
11980 case VMX_EXIT_NMI_WINDOW:
11981 case VMX_EXIT_TASK_SWITCH:
11982 case VMX_EXIT_TPR_BELOW_THRESHOLD:
11983 case VMX_EXIT_APIC_ACCESS:
11984 case VMX_EXIT_EPT_VIOLATION:
11985 case VMX_EXIT_EPT_MISCONFIG:
11986 case VMX_EXIT_PREEMPT_TIMER:
11987
11988 /* Instruction specific VM-exits: */
11989 case VMX_EXIT_CPUID:
11990 case VMX_EXIT_GETSEC:
11991 case VMX_EXIT_HLT:
11992 case VMX_EXIT_INVD:
11993 case VMX_EXIT_INVLPG:
11994 case VMX_EXIT_RDPMC:
11995 case VMX_EXIT_RDTSC:
11996 case VMX_EXIT_RSM:
11997 case VMX_EXIT_VMCALL:
11998 case VMX_EXIT_VMCLEAR:
11999 case VMX_EXIT_VMLAUNCH:
12000 case VMX_EXIT_VMPTRLD:
12001 case VMX_EXIT_VMPTRST:
12002 case VMX_EXIT_VMREAD:
12003 case VMX_EXIT_VMRESUME:
12004 case VMX_EXIT_VMWRITE:
12005 case VMX_EXIT_VMXOFF:
12006 case VMX_EXIT_VMXON:
12007 case VMX_EXIT_MOV_CRX:
12008 case VMX_EXIT_MOV_DRX:
12009 case VMX_EXIT_IO_INSTR:
12010 case VMX_EXIT_RDMSR:
12011 case VMX_EXIT_WRMSR:
12012 case VMX_EXIT_MWAIT:
12013 case VMX_EXIT_MONITOR:
12014 case VMX_EXIT_PAUSE:
12015 case VMX_EXIT_GDTR_IDTR_ACCESS:
12016 case VMX_EXIT_LDTR_TR_ACCESS:
12017 case VMX_EXIT_INVEPT:
12018 case VMX_EXIT_RDTSCP:
12019 case VMX_EXIT_INVVPID:
12020 case VMX_EXIT_WBINVD:
12021 case VMX_EXIT_XSETBV:
12022 case VMX_EXIT_RDRAND:
12023 case VMX_EXIT_INVPCID:
12024 case VMX_EXIT_VMFUNC:
12025 case VMX_EXIT_RDSEED:
12026 case VMX_EXIT_XSAVES:
12027 case VMX_EXIT_XRSTORS:
12028 {
12029 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12030 AssertRCReturn(rc, rc);
12031 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12032 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12033 return VINF_EM_DBG_STEPPED;
12034 break;
12035 }
12036
12037 /* Errors and unexpected events: */
12038 case VMX_EXIT_INIT_SIGNAL:
12039 case VMX_EXIT_SIPI:
12040 case VMX_EXIT_IO_SMI:
12041 case VMX_EXIT_SMI:
12042 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12043 case VMX_EXIT_ERR_MSR_LOAD:
12044 case VMX_EXIT_ERR_MACHINE_CHECK:
12045 case VMX_EXIT_PML_FULL:
12046 case VMX_EXIT_VIRTUALIZED_EOI:
12047 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12048 break;
12049
12050 default:
12051 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12052 break;
12053 }
12054 }
12055
12056 /*
12057 * Check for debugger event breakpoints and dtrace probes.
12058 */
12059 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12060 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12061 {
12062 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12063 if (rcStrict != VINF_SUCCESS)
12064 return rcStrict;
12065 }
12066
12067 /*
12068 * Normal processing.
12069 */
12070#ifdef HMVMX_USE_FUNCTION_TABLE
12071 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12072#else
12073 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12074#endif
12075}
12076
12077
12078/**
12079 * Single steps guest code using hardware-assisted VMX.
12080 *
12081 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12082 * but single-stepping through the hypervisor debugger.
12083 *
12084 * @returns Strict VBox status code (i.e. informational status codes too).
12085 * @param pVCpu The cross context virtual CPU structure.
12086 * @param pcLoops Pointer to the number of executed loops.
12087 *
12088 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12089 */
12090static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPUCC pVCpu, uint32_t *pcLoops)
12091{
12092 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12093 Assert(pcLoops);
12094 Assert(*pcLoops <= cMaxResumeLoops);
12095
12096 VMXTRANSIENT VmxTransient;
12097 RT_ZERO(VmxTransient);
12098 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12099
12100 /* Set HMCPU indicators. */
12101 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12102 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12103 pVCpu->hm.s.fDebugWantRdTscExit = false;
12104 pVCpu->hm.s.fUsingDebugLoop = true;
12105
12106 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12107 VMXRUNDBGSTATE DbgState;
12108 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12109 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12110
12111 /*
12112 * The loop.
12113 */
12114 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12115 for (;;)
12116 {
12117 Assert(!HMR0SuspendPending());
12118 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12119 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12120 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12121
12122 /* Set up VM-execution controls the next two can respond to. */
12123 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12124
12125 /*
12126 * Preparatory work for running guest code, this may force us to
12127 * return to ring-3.
12128 *
12129 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12130 */
12131 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12132 if (rcStrict != VINF_SUCCESS)
12133 break;
12134
12135 /* Interrupts are disabled at this point! */
12136 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12137
12138 /* Override any obnoxious code in the above two calls. */
12139 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12140
12141 /*
12142 * Finally execute the guest.
12143 */
12144 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12145
12146 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12147 /* Interrupts are re-enabled at this point! */
12148
12149 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12150 if (RT_SUCCESS(rcRun))
12151 { /* very likely */ }
12152 else
12153 {
12154 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12155 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12156 return rcRun;
12157 }
12158
12159 /* Profile the VM-exit. */
12160 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12161 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12162 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12163 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12164 HMVMX_START_EXIT_DISPATCH_PROF();
12165
12166 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12167
12168 /*
12169 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12170 */
12171 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12172 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12173 if (rcStrict != VINF_SUCCESS)
12174 break;
12175 if (++(*pcLoops) > cMaxResumeLoops)
12176 {
12177 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12178 rcStrict = VINF_EM_RAW_INTERRUPT;
12179 break;
12180 }
12181
12182 /*
12183 * Stepping: Did the RIP change, if so, consider it a single step.
12184 * Otherwise, make sure one of the TFs gets set.
12185 */
12186 if (fStepping)
12187 {
12188 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12189 AssertRC(rc);
12190 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12191 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12192 {
12193 rcStrict = VINF_EM_DBG_STEPPED;
12194 break;
12195 }
12196 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12197 }
12198
12199 /*
12200 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12201 */
12202 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12203 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12204 }
12205
12206 /*
12207 * Clear the X86_EFL_TF if necessary.
12208 */
12209 if (pVCpu->hm.s.fClearTrapFlag)
12210 {
12211 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12212 AssertRC(rc);
12213 pVCpu->hm.s.fClearTrapFlag = false;
12214 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12215 }
12216 /** @todo there seems to be issues with the resume flag when the monitor trap
12217 * flag is pending without being used. Seen early in bios init when
12218 * accessing APIC page in protected mode. */
12219
12220 /*
12221 * Restore VM-exit control settings as we may not re-enter this function the
12222 * next time around.
12223 */
12224 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
12225
12226 /* Restore HMCPU indicators. */
12227 pVCpu->hm.s.fUsingDebugLoop = false;
12228 pVCpu->hm.s.fDebugWantRdTscExit = false;
12229 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
12230
12231 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
12232 return rcStrict;
12233}
12234
12235
12236/** @} */
12237
12238
12239/**
12240 * Checks if any expensive dtrace probes are enabled and we should go to the
12241 * debug loop.
12242 *
12243 * @returns true if we should use debug loop, false if not.
12244 */
12245static bool hmR0VmxAnyExpensiveProbesEnabled(void)
12246{
12247 /* It's probably faster to OR the raw 32-bit counter variables together.
12248 Since the variables are in an array and the probes are next to one
12249 another (more or less), we have good locality. So, better read
12250 eight-nine cache lines ever time and only have one conditional, than
12251 128+ conditionals, right? */
12252 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
12253 | VBOXVMM_XCPT_DE_ENABLED_RAW()
12254 | VBOXVMM_XCPT_DB_ENABLED_RAW()
12255 | VBOXVMM_XCPT_BP_ENABLED_RAW()
12256 | VBOXVMM_XCPT_OF_ENABLED_RAW()
12257 | VBOXVMM_XCPT_BR_ENABLED_RAW()
12258 | VBOXVMM_XCPT_UD_ENABLED_RAW()
12259 | VBOXVMM_XCPT_NM_ENABLED_RAW()
12260 | VBOXVMM_XCPT_DF_ENABLED_RAW()
12261 | VBOXVMM_XCPT_TS_ENABLED_RAW()
12262 | VBOXVMM_XCPT_NP_ENABLED_RAW()
12263 | VBOXVMM_XCPT_SS_ENABLED_RAW()
12264 | VBOXVMM_XCPT_GP_ENABLED_RAW()
12265 | VBOXVMM_XCPT_PF_ENABLED_RAW()
12266 | VBOXVMM_XCPT_MF_ENABLED_RAW()
12267 | VBOXVMM_XCPT_AC_ENABLED_RAW()
12268 | VBOXVMM_XCPT_XF_ENABLED_RAW()
12269 | VBOXVMM_XCPT_VE_ENABLED_RAW()
12270 | VBOXVMM_XCPT_SX_ENABLED_RAW()
12271 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
12272 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
12273 ) != 0
12274 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
12275 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
12276 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
12277 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
12278 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
12279 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
12280 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
12281 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
12282 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
12283 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
12284 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
12285 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
12286 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
12287 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
12288 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
12289 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
12290 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
12291 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
12292 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
12293 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
12294 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
12295 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
12296 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
12297 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
12298 | VBOXVMM_INSTR_STR_ENABLED_RAW()
12299 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
12300 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
12301 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
12302 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
12303 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
12304 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
12305 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
12306 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
12307 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
12308 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
12309 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
12310 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
12311 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
12312 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
12313 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
12314 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
12315 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
12316 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
12317 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
12318 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
12319 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
12320 ) != 0
12321 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
12322 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
12323 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
12324 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
12325 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
12326 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
12327 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
12328 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
12329 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
12330 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
12331 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
12332 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
12333 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
12334 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
12335 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
12336 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
12337 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
12338 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
12339 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
12340 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
12341 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
12342 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
12343 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
12344 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
12345 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
12346 | VBOXVMM_EXIT_STR_ENABLED_RAW()
12347 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
12348 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
12349 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
12350 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
12351 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
12352 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
12353 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
12354 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
12355 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
12356 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
12357 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
12358 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
12359 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
12360 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
12361 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
12362 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
12363 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
12364 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
12365 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
12366 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
12367 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
12368 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
12369 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
12370 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
12371 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
12372 ) != 0;
12373}
12374
12375
12376/**
12377 * Runs the guest using hardware-assisted VMX.
12378 *
12379 * @returns Strict VBox status code (i.e. informational status codes too).
12380 * @param pVCpu The cross context virtual CPU structure.
12381 */
12382VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPUCC pVCpu)
12383{
12384 AssertPtr(pVCpu);
12385 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12386 Assert(VMMRZCallRing3IsEnabled(pVCpu));
12387 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12388 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
12389
12390 VBOXSTRICTRC rcStrict;
12391 uint32_t cLoops = 0;
12392 for (;;)
12393 {
12394#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12395 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
12396#else
12397 NOREF(pCtx);
12398 bool const fInNestedGuestMode = false;
12399#endif
12400 if (!fInNestedGuestMode)
12401 {
12402 if ( !pVCpu->hm.s.fUseDebugLoop
12403 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
12404 && !DBGFIsStepping(pVCpu)
12405 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
12406 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
12407 else
12408 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
12409 }
12410#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12411 else
12412 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
12413
12414 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
12415 {
12416 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
12417 continue;
12418 }
12419 if (rcStrict == VINF_VMX_VMEXIT)
12420 {
12421 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
12422 continue;
12423 }
12424#endif
12425 break;
12426 }
12427
12428 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
12429 switch (rcLoop)
12430 {
12431 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
12432 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
12433 }
12434
12435 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
12436 if (RT_FAILURE(rc2))
12437 {
12438 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
12439 rcStrict = rc2;
12440 }
12441 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
12442 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
12443 return rcStrict;
12444}
12445
12446
12447#ifndef HMVMX_USE_FUNCTION_TABLE
12448/**
12449 * Handles a guest VM-exit from hardware-assisted VMX execution.
12450 *
12451 * @returns Strict VBox status code (i.e. informational status codes too).
12452 * @param pVCpu The cross context virtual CPU structure.
12453 * @param pVmxTransient The VMX-transient structure.
12454 */
12455DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12456{
12457#ifdef DEBUG_ramshankar
12458# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
12459 do { \
12460 if (a_fSave != 0) \
12461 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
12462 VBOXSTRICTRC rcStrict = a_CallExpr; \
12463 if (a_fSave != 0) \
12464 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
12465 return rcStrict; \
12466 } while (0)
12467#else
12468# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
12469#endif
12470 uint32_t const uExitReason = pVmxTransient->uExitReason;
12471 switch (uExitReason)
12472 {
12473 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
12474 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
12475 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
12476 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
12477 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
12478 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
12479 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
12480 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
12481 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
12482 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
12483 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
12484 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
12485 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
12486 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
12487 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
12488 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
12489 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
12490 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
12491 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
12492 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
12493 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
12494 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
12495 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
12496 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
12497 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
12498 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
12499 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
12500 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
12501 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
12502 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
12503#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12504 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
12505 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
12506 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
12507 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
12508 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
12509 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
12510 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
12511 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
12512 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
12513 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
12514 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
12515#else
12516 case VMX_EXIT_VMCLEAR:
12517 case VMX_EXIT_VMLAUNCH:
12518 case VMX_EXIT_VMPTRLD:
12519 case VMX_EXIT_VMPTRST:
12520 case VMX_EXIT_VMREAD:
12521 case VMX_EXIT_VMRESUME:
12522 case VMX_EXIT_VMWRITE:
12523 case VMX_EXIT_VMXOFF:
12524 case VMX_EXIT_VMXON:
12525 case VMX_EXIT_INVVPID:
12526 case VMX_EXIT_INVEPT:
12527 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
12528#endif
12529
12530 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
12531 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
12532 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
12533
12534 case VMX_EXIT_INIT_SIGNAL:
12535 case VMX_EXIT_SIPI:
12536 case VMX_EXIT_IO_SMI:
12537 case VMX_EXIT_SMI:
12538 case VMX_EXIT_ERR_MSR_LOAD:
12539 case VMX_EXIT_ERR_MACHINE_CHECK:
12540 case VMX_EXIT_PML_FULL:
12541 case VMX_EXIT_VIRTUALIZED_EOI:
12542 case VMX_EXIT_GDTR_IDTR_ACCESS:
12543 case VMX_EXIT_LDTR_TR_ACCESS:
12544 case VMX_EXIT_APIC_WRITE:
12545 case VMX_EXIT_RDRAND:
12546 case VMX_EXIT_RSM:
12547 case VMX_EXIT_VMFUNC:
12548 case VMX_EXIT_ENCLS:
12549 case VMX_EXIT_RDSEED:
12550 case VMX_EXIT_XSAVES:
12551 case VMX_EXIT_XRSTORS:
12552 case VMX_EXIT_UMWAIT:
12553 case VMX_EXIT_TPAUSE:
12554 default:
12555 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12556 }
12557#undef VMEXIT_CALL_RET
12558}
12559#endif /* !HMVMX_USE_FUNCTION_TABLE */
12560
12561
12562#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12563/**
12564 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
12565 *
12566 * @returns Strict VBox status code (i.e. informational status codes too).
12567 * @param pVCpu The cross context virtual CPU structure.
12568 * @param pVmxTransient The VMX-transient structure.
12569 */
12570DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12571{
12572 /** @todo NSTVMX: Remove after debugging page-fault issue. */
12573#ifdef DEBUG_ramshankar
12574 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12575 Log4Func(("cs:rip=%#04x:%#RX64 rsp=%#RX64 eflags=%#RX32 cr3=%#RX64\n", pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
12576 pVCpu->cpum.GstCtx.rsp, pVCpu->cpum.GstCtx.eflags.u32, pVCpu->cpum.GstCtx.cr3));
12577#endif
12578
12579 uint32_t const uExitReason = pVmxTransient->uExitReason;
12580 switch (uExitReason)
12581 {
12582 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
12583 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
12584 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
12585 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
12586 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
12587
12588 /*
12589 * We shouldn't direct host physical interrupts to the nested-guest.
12590 */
12591 case VMX_EXIT_EXT_INT:
12592 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
12593
12594 /*
12595 * Instructions that cause VM-exits unconditionally or the condition is
12596 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12597 * happens, it's guaranteed to be a nested-guest VM-exit).
12598 *
12599 * - Provides VM-exit instruction length ONLY.
12600 */
12601 case VMX_EXIT_CPUID: /* Unconditional. */
12602 case VMX_EXIT_VMCALL:
12603 case VMX_EXIT_GETSEC:
12604 case VMX_EXIT_INVD:
12605 case VMX_EXIT_XSETBV:
12606 case VMX_EXIT_VMLAUNCH:
12607 case VMX_EXIT_VMRESUME:
12608 case VMX_EXIT_VMXOFF:
12609 case VMX_EXIT_ENCLS: /* Condition specified solely by nested hypervisor. */
12610 case VMX_EXIT_VMFUNC:
12611 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
12612
12613 /*
12614 * Instructions that cause VM-exits unconditionally or the condition is
12615 * always is taken solely from the nested hypervisor (meaning if the VM-exit
12616 * happens, it's guaranteed to be a nested-guest VM-exit).
12617 *
12618 * - Provides VM-exit instruction length.
12619 * - Provides VM-exit information.
12620 * - Optionally provides Exit qualification.
12621 *
12622 * Since Exit qualification is 0 for all VM-exits where it is not
12623 * applicable, reading and passing it to the guest should produce
12624 * defined behavior.
12625 *
12626 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
12627 */
12628 case VMX_EXIT_INVEPT: /* Unconditional. */
12629 case VMX_EXIT_INVVPID:
12630 case VMX_EXIT_VMCLEAR:
12631 case VMX_EXIT_VMPTRLD:
12632 case VMX_EXIT_VMPTRST:
12633 case VMX_EXIT_VMXON:
12634 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by nested hypervisor. */
12635 case VMX_EXIT_LDTR_TR_ACCESS:
12636 case VMX_EXIT_RDRAND:
12637 case VMX_EXIT_RDSEED:
12638 case VMX_EXIT_XSAVES:
12639 case VMX_EXIT_XRSTORS:
12640 case VMX_EXIT_UMWAIT:
12641 case VMX_EXIT_TPAUSE:
12642 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
12643
12644 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
12645 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
12646 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
12647 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
12648 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
12649 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
12650 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
12651 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
12652 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
12653 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
12654 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
12655 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
12656 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
12657 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
12658 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
12659 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
12660 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
12661 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
12662 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
12663
12664 case VMX_EXIT_PREEMPT_TIMER:
12665 {
12666 /** @todo NSTVMX: Preempt timer. */
12667 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
12668 }
12669
12670 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
12671 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
12672
12673 case VMX_EXIT_VMREAD:
12674 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
12675
12676 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
12677 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
12678
12679 case VMX_EXIT_INIT_SIGNAL:
12680 case VMX_EXIT_SIPI:
12681 case VMX_EXIT_IO_SMI:
12682 case VMX_EXIT_SMI:
12683 case VMX_EXIT_ERR_MSR_LOAD:
12684 case VMX_EXIT_ERR_MACHINE_CHECK:
12685 case VMX_EXIT_PML_FULL:
12686 case VMX_EXIT_RSM:
12687 default:
12688 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
12689 }
12690}
12691#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12692
12693
12694/** @name VM-exit helpers.
12695 * @{
12696 */
12697/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12698/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
12699/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
12700
12701/** Macro for VM-exits called unexpectedly. */
12702#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
12703 do { \
12704 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
12705 return VERR_VMX_UNEXPECTED_EXIT; \
12706 } while (0)
12707
12708#ifdef VBOX_STRICT
12709/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
12710# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
12711 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
12712
12713# define HMVMX_ASSERT_PREEMPT_CPUID() \
12714 do { \
12715 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
12716 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
12717 } while (0)
12718
12719# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12720 do { \
12721 AssertPtr((a_pVCpu)); \
12722 AssertPtr((a_pVmxTransient)); \
12723 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
12724 Assert((a_pVmxTransient)->pVmcsInfo); \
12725 Assert(ASMIntAreEnabled()); \
12726 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12727 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
12728 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
12729 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
12730 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
12731 HMVMX_ASSERT_PREEMPT_CPUID(); \
12732 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12733 } while (0)
12734
12735# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12736 do { \
12737 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
12738 Assert((a_pVmxTransient)->fIsNestedGuest); \
12739 } while (0)
12740
12741# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12742 do { \
12743 Log4Func(("\n")); \
12744 } while (0)
12745#else
12746# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12747 do { \
12748 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
12749 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
12750 } while (0)
12751
12752# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
12753 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
12754
12755# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
12756#endif
12757
12758#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
12759/** Macro that does the necessary privilege checks and intercepted VM-exits for
12760 * guests that attempted to execute a VMX instruction. */
12761# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
12762 do \
12763 { \
12764 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
12765 if (rcStrictTmp == VINF_SUCCESS) \
12766 { /* likely */ } \
12767 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12768 { \
12769 Assert((a_pVCpu)->hm.s.Event.fPending); \
12770 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
12771 return VINF_SUCCESS; \
12772 } \
12773 else \
12774 { \
12775 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
12776 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
12777 } \
12778 } while (0)
12779
12780/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
12781# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
12782 do \
12783 { \
12784 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
12785 (a_pGCPtrEffAddr)); \
12786 if (rcStrictTmp == VINF_SUCCESS) \
12787 { /* likely */ } \
12788 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
12789 { \
12790 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
12791 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
12792 NOREF(uXcptTmp); \
12793 return VINF_SUCCESS; \
12794 } \
12795 else \
12796 { \
12797 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
12798 return rcStrictTmp; \
12799 } \
12800 } while (0)
12801#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
12802
12803
12804/**
12805 * Advances the guest RIP by the specified number of bytes.
12806 *
12807 * @param pVCpu The cross context virtual CPU structure.
12808 * @param cbInstr Number of bytes to advance the RIP by.
12809 *
12810 * @remarks No-long-jump zone!!!
12811 */
12812DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPUCC pVCpu, uint32_t cbInstr)
12813{
12814 /* Advance the RIP. */
12815 pVCpu->cpum.GstCtx.rip += cbInstr;
12816 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
12817
12818 /* Update interrupt inhibition. */
12819 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
12820 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
12821 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
12822}
12823
12824
12825/**
12826 * Advances the guest RIP after reading it from the VMCS.
12827 *
12828 * @returns VBox status code, no informational status codes.
12829 * @param pVCpu The cross context virtual CPU structure.
12830 * @param pVmxTransient The VMX-transient structure.
12831 *
12832 * @remarks No-long-jump zone!!!
12833 */
12834static int hmR0VmxAdvanceGuestRip(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12835{
12836 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
12837 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
12838 AssertRCReturn(rc, rc);
12839
12840 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbExitInstr);
12841 return VINF_SUCCESS;
12842}
12843
12844
12845/**
12846 * Handle a condition that occurred while delivering an event through the guest or
12847 * nested-guest IDT.
12848 *
12849 * @returns Strict VBox status code (i.e. informational status codes too).
12850 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
12851 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
12852 * to continue execution of the guest which will delivery the \#DF.
12853 * @retval VINF_EM_RESET if we detected a triple-fault condition.
12854 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
12855 *
12856 * @param pVCpu The cross context virtual CPU structure.
12857 * @param pVmxTransient The VMX-transient structure.
12858 *
12859 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
12860 * Additionally, HMVMX_READ_EXIT_QUALIFICATION is required if the VM-exit
12861 * is due to an EPT violation, PML full or SPP-related event.
12862 *
12863 * @remarks No-long-jump zone!!!
12864 */
12865static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
12866{
12867 Assert(!pVCpu->hm.s.Event.fPending);
12868 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
12869 if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
12870 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
12871 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
12872 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_EXIT_QUALIFICATION);
12873
12874 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
12875 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
12876 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
12877 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
12878 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
12879 {
12880 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
12881 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
12882
12883 /*
12884 * If the event was a software interrupt (generated with INT n) or a software exception
12885 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
12886 * can handle the VM-exit and continue guest execution which will re-execute the
12887 * instruction rather than re-injecting the exception, as that can cause premature
12888 * trips to ring-3 before injection and involve TRPM which currently has no way of
12889 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
12890 * the problem).
12891 */
12892 IEMXCPTRAISE enmRaise;
12893 IEMXCPTRAISEINFO fRaiseInfo;
12894 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
12895 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
12896 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
12897 {
12898 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
12899 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12900 }
12901 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
12902 {
12903 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
12904 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
12905 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
12906
12907 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
12908 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
12909
12910 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
12911
12912 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
12913 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
12914 {
12915 pVmxTransient->fVectoringPF = true;
12916 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12917 }
12918 }
12919 else
12920 {
12921 /*
12922 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
12923 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
12924 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
12925 */
12926 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
12927 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12928 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
12929 enmRaise = IEMXCPTRAISE_PREV_EVENT;
12930 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
12931 }
12932
12933 /*
12934 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
12935 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
12936 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
12937 * subsequent VM-entry would fail, see @bugref{7445}.
12938 *
12939 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
12940 */
12941 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
12942 && enmRaise == IEMXCPTRAISE_PREV_EVENT
12943 && (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
12944 && CPUMIsGuestNmiBlocking(pVCpu))
12945 {
12946 CPUMSetGuestNmiBlocking(pVCpu, false);
12947 }
12948
12949 switch (enmRaise)
12950 {
12951 case IEMXCPTRAISE_CURRENT_XCPT:
12952 {
12953 Log4Func(("IDT: Pending secondary Xcpt: idtinfo=%#RX64 exitinfo=%#RX64\n", uIdtVectorInfo, uExitIntInfo));
12954 Assert(rcStrict == VINF_SUCCESS);
12955 break;
12956 }
12957
12958 case IEMXCPTRAISE_PREV_EVENT:
12959 {
12960 uint32_t u32ErrCode;
12961 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
12962 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
12963 else
12964 u32ErrCode = 0;
12965
12966 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
12967 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
12968 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
12969 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
12970
12971 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
12972 pVCpu->hm.s.Event.u32ErrCode));
12973 Assert(rcStrict == VINF_SUCCESS);
12974 break;
12975 }
12976
12977 case IEMXCPTRAISE_REEXEC_INSTR:
12978 Assert(rcStrict == VINF_SUCCESS);
12979 break;
12980
12981 case IEMXCPTRAISE_DOUBLE_FAULT:
12982 {
12983 /*
12984 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
12985 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
12986 */
12987 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
12988 {
12989 pVmxTransient->fVectoringDoublePF = true;
12990 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
12991 pVCpu->cpum.GstCtx.cr2));
12992 rcStrict = VINF_SUCCESS;
12993 }
12994 else
12995 {
12996 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
12997 hmR0VmxSetPendingXcptDF(pVCpu);
12998 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
12999 uIdtVector, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13000 rcStrict = VINF_HM_DOUBLE_FAULT;
13001 }
13002 break;
13003 }
13004
13005 case IEMXCPTRAISE_TRIPLE_FAULT:
13006 {
13007 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector,
13008 VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo)));
13009 rcStrict = VINF_EM_RESET;
13010 break;
13011 }
13012
13013 case IEMXCPTRAISE_CPU_HANG:
13014 {
13015 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13016 rcStrict = VERR_EM_GUEST_CPU_HANG;
13017 break;
13018 }
13019
13020 default:
13021 {
13022 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13023 rcStrict = VERR_VMX_IPE_2;
13024 break;
13025 }
13026 }
13027 }
13028 else if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
13029 && !CPUMIsGuestNmiBlocking(pVCpu))
13030 {
13031 if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13032 && VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo) != X86_XCPT_DF
13033 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo))
13034 {
13035 /*
13036 * Execution of IRET caused a fault when NMI blocking was in effect (i.e we're in
13037 * the guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13038 * that NMIs remain blocked until the IRET execution is completed.
13039 *
13040 * See Intel spec. 31.7.1.2 "Resuming Guest Software After Handling An Exception".
13041 */
13042 CPUMSetGuestNmiBlocking(pVCpu, true);
13043 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13044 }
13045 else if ( pVmxTransient->uExitReason == VMX_EXIT_EPT_VIOLATION
13046 || pVmxTransient->uExitReason == VMX_EXIT_PML_FULL
13047 || pVmxTransient->uExitReason == VMX_EXIT_SPP_EVENT)
13048 {
13049 /*
13050 * Execution of IRET caused an EPT violation, page-modification log-full event or
13051 * SPP-related event VM-exit when NMI blocking was in effect (i.e. we're in the
13052 * guest or nested-guest NMI handler). We need to set the block-by-NMI field so
13053 * that NMIs remain blocked until the IRET execution is completed.
13054 *
13055 * See Intel spec. 27.2.3 "Information about NMI unblocking due to IRET"
13056 */
13057 if (VMX_EXIT_QUAL_EPT_IS_NMI_UNBLOCK_IRET(pVmxTransient->uExitQual))
13058 {
13059 CPUMSetGuestNmiBlocking(pVCpu, true);
13060 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13061 }
13062 }
13063 }
13064
13065 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13066 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13067 return rcStrict;
13068}
13069
13070
13071#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13072/**
13073 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13074 * guest attempting to execute a VMX instruction.
13075 *
13076 * @returns Strict VBox status code (i.e. informational status codes too).
13077 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13078 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13079 *
13080 * @param pVCpu The cross context virtual CPU structure.
13081 * @param uExitReason The VM-exit reason.
13082 *
13083 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13084 * @remarks No-long-jump zone!!!
13085 */
13086static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPUCC pVCpu, uint32_t uExitReason)
13087{
13088 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13089 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13090
13091 /*
13092 * The physical CPU would have already checked the CPU mode/code segment.
13093 * We shall just assert here for paranoia.
13094 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13095 */
13096 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13097 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13098 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13099
13100 if (uExitReason == VMX_EXIT_VMXON)
13101 {
13102 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13103
13104 /*
13105 * We check CR4.VMXE because it is required to be always set while in VMX operation
13106 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13107 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13108 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13109 */
13110 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13111 {
13112 Log4Func(("CR4.VMXE is not set -> #UD\n"));
13113 hmR0VmxSetPendingXcptUD(pVCpu);
13114 return VINF_HM_PENDING_XCPT;
13115 }
13116 }
13117 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
13118 {
13119 /*
13120 * The guest has not entered VMX operation but attempted to execute a VMX instruction
13121 * (other than VMXON), we need to raise a #UD.
13122 */
13123 Log4Func(("Not in VMX root mode -> #UD\n"));
13124 hmR0VmxSetPendingXcptUD(pVCpu);
13125 return VINF_HM_PENDING_XCPT;
13126 }
13127
13128 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
13129 return VINF_SUCCESS;
13130}
13131
13132
13133/**
13134 * Decodes the memory operand of an instruction that caused a VM-exit.
13135 *
13136 * The Exit qualification field provides the displacement field for memory
13137 * operand instructions, if any.
13138 *
13139 * @returns Strict VBox status code (i.e. informational status codes too).
13140 * @retval VINF_SUCCESS if the operand was successfully decoded.
13141 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
13142 * operand.
13143 * @param pVCpu The cross context virtual CPU structure.
13144 * @param uExitInstrInfo The VM-exit instruction information field.
13145 * @param enmMemAccess The memory operand's access type (read or write).
13146 * @param GCPtrDisp The instruction displacement field, if any. For
13147 * RIP-relative addressing pass RIP + displacement here.
13148 * @param pGCPtrMem Where to store the effective destination memory address.
13149 *
13150 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
13151 * virtual-8086 mode hence skips those checks while verifying if the
13152 * segment is valid.
13153 */
13154static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPUCC pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
13155 PRTGCPTR pGCPtrMem)
13156{
13157 Assert(pGCPtrMem);
13158 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
13159 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
13160 | CPUMCTX_EXTRN_CR0);
13161
13162 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
13163 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
13164 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
13165
13166 VMXEXITINSTRINFO ExitInstrInfo;
13167 ExitInstrInfo.u = uExitInstrInfo;
13168 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
13169 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
13170 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
13171 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
13172 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
13173 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
13174 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
13175 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
13176 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
13177
13178 /*
13179 * Validate instruction information.
13180 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
13181 */
13182 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
13183 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
13184 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
13185 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
13186 AssertLogRelMsgReturn(fIsMemOperand,
13187 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
13188
13189 /*
13190 * Compute the complete effective address.
13191 *
13192 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
13193 * See AMD spec. 4.5.2 "Segment Registers".
13194 */
13195 RTGCPTR GCPtrMem = GCPtrDisp;
13196 if (fBaseRegValid)
13197 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
13198 if (fIdxRegValid)
13199 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
13200
13201 RTGCPTR const GCPtrOff = GCPtrMem;
13202 if ( !fIsLongMode
13203 || iSegReg >= X86_SREG_FS)
13204 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
13205 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
13206
13207 /*
13208 * Validate effective address.
13209 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
13210 */
13211 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
13212 Assert(cbAccess > 0);
13213 if (fIsLongMode)
13214 {
13215 if (X86_IS_CANONICAL(GCPtrMem))
13216 {
13217 *pGCPtrMem = GCPtrMem;
13218 return VINF_SUCCESS;
13219 }
13220
13221 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
13222 * "Data Limit Checks in 64-bit Mode". */
13223 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
13224 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13225 return VINF_HM_PENDING_XCPT;
13226 }
13227
13228 /*
13229 * This is a watered down version of iemMemApplySegment().
13230 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
13231 * and segment CPL/DPL checks are skipped.
13232 */
13233 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
13234 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
13235 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
13236
13237 /* Check if the segment is present and usable. */
13238 if ( pSel->Attr.n.u1Present
13239 && !pSel->Attr.n.u1Unusable)
13240 {
13241 Assert(pSel->Attr.n.u1DescType);
13242 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
13243 {
13244 /* Check permissions for the data segment. */
13245 if ( enmMemAccess == VMXMEMACCESS_WRITE
13246 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
13247 {
13248 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13249 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
13250 return VINF_HM_PENDING_XCPT;
13251 }
13252
13253 /* Check limits if it's a normal data segment. */
13254 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
13255 {
13256 if ( GCPtrFirst32 > pSel->u32Limit
13257 || GCPtrLast32 > pSel->u32Limit)
13258 {
13259 Log4Func(("Data segment limit exceeded. "
13260 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13261 GCPtrLast32, pSel->u32Limit));
13262 if (iSegReg == X86_SREG_SS)
13263 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13264 else
13265 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13266 return VINF_HM_PENDING_XCPT;
13267 }
13268 }
13269 else
13270 {
13271 /* Check limits if it's an expand-down data segment.
13272 Note! The upper boundary is defined by the B bit, not the G bit! */
13273 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
13274 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
13275 {
13276 Log4Func(("Expand-down data segment limit exceeded. "
13277 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
13278 GCPtrLast32, pSel->u32Limit));
13279 if (iSegReg == X86_SREG_SS)
13280 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13281 else
13282 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13283 return VINF_HM_PENDING_XCPT;
13284 }
13285 }
13286 }
13287 else
13288 {
13289 /* Check permissions for the code segment. */
13290 if ( enmMemAccess == VMXMEMACCESS_WRITE
13291 || ( enmMemAccess == VMXMEMACCESS_READ
13292 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
13293 {
13294 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
13295 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13296 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13297 return VINF_HM_PENDING_XCPT;
13298 }
13299
13300 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
13301 if ( GCPtrFirst32 > pSel->u32Limit
13302 || GCPtrLast32 > pSel->u32Limit)
13303 {
13304 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
13305 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
13306 if (iSegReg == X86_SREG_SS)
13307 hmR0VmxSetPendingXcptSS(pVCpu, 0);
13308 else
13309 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13310 return VINF_HM_PENDING_XCPT;
13311 }
13312 }
13313 }
13314 else
13315 {
13316 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
13317 hmR0VmxSetPendingXcptGP(pVCpu, 0);
13318 return VINF_HM_PENDING_XCPT;
13319 }
13320
13321 *pGCPtrMem = GCPtrMem;
13322 return VINF_SUCCESS;
13323}
13324#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13325
13326
13327/**
13328 * VM-exit helper for LMSW.
13329 */
13330static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
13331{
13332 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13333 AssertRCReturn(rc, rc);
13334
13335 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
13336 AssertMsg( rcStrict == VINF_SUCCESS
13337 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13338
13339 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13340 if (rcStrict == VINF_IEM_RAISED_XCPT)
13341 {
13342 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13343 rcStrict = VINF_SUCCESS;
13344 }
13345
13346 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
13347 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13348 return rcStrict;
13349}
13350
13351
13352/**
13353 * VM-exit helper for CLTS.
13354 */
13355static VBOXSTRICTRC hmR0VmxExitClts(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
13356{
13357 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13358 AssertRCReturn(rc, rc);
13359
13360 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
13361 AssertMsg( rcStrict == VINF_SUCCESS
13362 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13363
13364 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
13365 if (rcStrict == VINF_IEM_RAISED_XCPT)
13366 {
13367 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13368 rcStrict = VINF_SUCCESS;
13369 }
13370
13371 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
13372 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13373 return rcStrict;
13374}
13375
13376
13377/**
13378 * VM-exit helper for MOV from CRx (CRx read).
13379 */
13380static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13381{
13382 Assert(iCrReg < 16);
13383 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
13384
13385 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13386 AssertRCReturn(rc, rc);
13387
13388 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
13389 AssertMsg( rcStrict == VINF_SUCCESS
13390 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13391
13392 if (iGReg == X86_GREG_xSP)
13393 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
13394 else
13395 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
13396#ifdef VBOX_WITH_STATISTICS
13397 switch (iCrReg)
13398 {
13399 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
13400 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
13401 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
13402 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
13403 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
13404 }
13405#endif
13406 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
13407 return rcStrict;
13408}
13409
13410
13411/**
13412 * VM-exit helper for MOV to CRx (CRx write).
13413 */
13414static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPUCC pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
13415{
13416 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
13417 AssertRCReturn(rc, rc);
13418
13419 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
13420 AssertMsg( rcStrict == VINF_SUCCESS
13421 || rcStrict == VINF_IEM_RAISED_XCPT
13422 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
13423
13424 switch (iCrReg)
13425 {
13426 case 0:
13427 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0
13428 | HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
13429 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
13430 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
13431 break;
13432
13433 case 2:
13434 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
13435 /* Nothing to do here, CR2 it's not part of the VMCS. */
13436 break;
13437
13438 case 3:
13439 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
13440 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
13441 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
13442 break;
13443
13444 case 4:
13445 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
13446 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
13447 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
13448 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
13449 break;
13450
13451 case 8:
13452 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
13453 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
13454 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
13455 break;
13456
13457 default:
13458 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
13459 break;
13460 }
13461
13462 if (rcStrict == VINF_IEM_RAISED_XCPT)
13463 {
13464 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13465 rcStrict = VINF_SUCCESS;
13466 }
13467 return rcStrict;
13468}
13469
13470
13471/**
13472 * VM-exit exception handler for \#PF (Page-fault exception).
13473 *
13474 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13475 */
13476static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13477{
13478 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13479 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
13480 hmR0VmxReadExitQualVmcs(pVmxTransient);
13481
13482 if (!pVM->hm.s.fNestedPaging)
13483 { /* likely */ }
13484 else
13485 {
13486#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
13487 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
13488#endif
13489 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
13490 if (!pVmxTransient->fVectoringDoublePF)
13491 {
13492 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13493 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
13494 }
13495 else
13496 {
13497 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13498 Assert(!pVmxTransient->fIsNestedGuest);
13499 hmR0VmxSetPendingXcptDF(pVCpu);
13500 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
13501 }
13502 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13503 return VINF_SUCCESS;
13504 }
13505
13506 Assert(!pVmxTransient->fIsNestedGuest);
13507
13508 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
13509 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
13510 if (pVmxTransient->fVectoringPF)
13511 {
13512 Assert(pVCpu->hm.s.Event.fPending);
13513 return VINF_EM_RAW_INJECT_TRPM_EVENT;
13514 }
13515
13516 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13517 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13518 AssertRCReturn(rc, rc);
13519
13520 Log4Func(("#PF: cs:rip=%#04x:%#RX64 err_code=%#RX32 exit_qual=%#RX64 cr3=%#RX64\n", pCtx->cs.Sel, pCtx->rip,
13521 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual, pCtx->cr3));
13522
13523 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
13524 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
13525
13526 Log4Func(("#PF: rc=%Rrc\n", rc));
13527 if (rc == VINF_SUCCESS)
13528 {
13529 /*
13530 * This is typically a shadow page table sync or a MMIO instruction. But we may have
13531 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
13532 */
13533 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13534 TRPMResetTrap(pVCpu);
13535 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
13536 return rc;
13537 }
13538
13539 if (rc == VINF_EM_RAW_GUEST_TRAP)
13540 {
13541 if (!pVmxTransient->fVectoringDoublePF)
13542 {
13543 /* It's a guest page fault and needs to be reflected to the guest. */
13544 uint32_t const uGstErrorCode = TRPMGetErrorCode(pVCpu);
13545 TRPMResetTrap(pVCpu);
13546 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
13547 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
13548 uGstErrorCode, pVmxTransient->uExitQual);
13549 }
13550 else
13551 {
13552 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
13553 TRPMResetTrap(pVCpu);
13554 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
13555 hmR0VmxSetPendingXcptDF(pVCpu);
13556 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
13557 }
13558
13559 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
13560 return VINF_SUCCESS;
13561 }
13562
13563 TRPMResetTrap(pVCpu);
13564 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
13565 return rc;
13566}
13567
13568
13569/**
13570 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
13571 *
13572 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13573 */
13574static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13575{
13576 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13577 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
13578
13579 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
13580 AssertRCReturn(rc, rc);
13581
13582 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
13583 {
13584 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
13585 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
13586
13587 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
13588 * provides VM-exit instruction length. If this causes problem later,
13589 * disassemble the instruction like it's done on AMD-V. */
13590 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13591 AssertRCReturn(rc2, rc2);
13592 return rc;
13593 }
13594
13595 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbExitInstr,
13596 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13597 return VINF_SUCCESS;
13598}
13599
13600
13601/**
13602 * VM-exit exception handler for \#BP (Breakpoint exception).
13603 *
13604 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13605 */
13606static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13607{
13608 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13609 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
13610
13611 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13612 AssertRCReturn(rc, rc);
13613
13614 if (!pVmxTransient->fIsNestedGuest)
13615 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
13616 else
13617 rc = VINF_EM_RAW_GUEST_TRAP;
13618
13619 if (rc == VINF_EM_RAW_GUEST_TRAP)
13620 {
13621 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13622 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13623 rc = VINF_SUCCESS;
13624 }
13625
13626 Assert(rc == VINF_SUCCESS || rc == VINF_EM_DBG_BREAKPOINT);
13627 return rc;
13628}
13629
13630
13631/**
13632 * VM-exit exception handler for \#AC (Alignment-check exception).
13633 *
13634 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13635 */
13636static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13637{
13638 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13639 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
13640
13641 /* Re-inject it. We'll detect any nesting before getting here. */
13642 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13643 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13644 return VINF_SUCCESS;
13645}
13646
13647
13648/**
13649 * VM-exit exception handler for \#DB (Debug exception).
13650 *
13651 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13652 */
13653static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13654{
13655 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13656 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
13657
13658 /*
13659 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
13660 */
13661 hmR0VmxReadExitQualVmcs(pVmxTransient);
13662
13663 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
13664 uint64_t const uDR6 = X86_DR6_INIT_VAL
13665 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
13666 | X86_DR6_BD | X86_DR6_BS));
13667
13668 int rc;
13669 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13670 if (!pVmxTransient->fIsNestedGuest)
13671 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
13672 else
13673 rc = VINF_EM_RAW_GUEST_TRAP;
13674 Log6Func(("rc=%Rrc\n", rc));
13675 if (rc == VINF_EM_RAW_GUEST_TRAP)
13676 {
13677 /*
13678 * The exception was for the guest. Update DR6, DR7.GD and
13679 * IA32_DEBUGCTL.LBR before forwarding it.
13680 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
13681 */
13682 VMMRZCallRing3Disable(pVCpu);
13683 HM_DISABLE_PREEMPT(pVCpu);
13684
13685 pCtx->dr[6] &= ~X86_DR6_B_MASK;
13686 pCtx->dr[6] |= uDR6;
13687 if (CPUMIsGuestDebugStateActive(pVCpu))
13688 ASMSetDR6(pCtx->dr[6]);
13689
13690 HM_RESTORE_PREEMPT();
13691 VMMRZCallRing3Enable(pVCpu);
13692
13693 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
13694 AssertRCReturn(rc, rc);
13695
13696 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
13697 pCtx->dr[7] &= ~(uint64_t)X86_DR7_GD;
13698
13699 /* Paranoia. */
13700 pCtx->dr[7] &= ~(uint64_t)X86_DR7_RAZ_MASK;
13701 pCtx->dr[7] |= X86_DR7_RA1_MASK;
13702
13703 rc = VMXWriteVmcsNw(VMX_VMCS_GUEST_DR7, pCtx->dr[7]);
13704 AssertRC(rc);
13705
13706 /*
13707 * Raise #DB in the guest.
13708 *
13709 * It is important to reflect exactly what the VM-exit gave us (preserving the
13710 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
13711 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
13712 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
13713 *
13714 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
13715 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
13716 */
13717 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13718 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13719 return VINF_SUCCESS;
13720 }
13721
13722 /*
13723 * Not a guest trap, must be a hypervisor related debug event then.
13724 * Update DR6 in case someone is interested in it.
13725 */
13726 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
13727 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
13728 CPUMSetHyperDR6(pVCpu, uDR6);
13729
13730 return rc;
13731}
13732
13733
13734/**
13735 * Hacks its way around the lovely mesa driver's backdoor accesses.
13736 *
13737 * @sa hmR0SvmHandleMesaDrvGp.
13738 */
13739static int hmR0VmxHandleMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13740{
13741 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
13742 RT_NOREF(pCtx);
13743
13744 /* For now we'll just skip the instruction. */
13745 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
13746}
13747
13748
13749/**
13750 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
13751 * backdoor logging w/o checking what it is running inside.
13752 *
13753 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
13754 * backdoor port and magic numbers loaded in registers.
13755 *
13756 * @returns true if it is, false if it isn't.
13757 * @sa hmR0SvmIsMesaDrvGp.
13758 */
13759DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
13760{
13761 /* 0xed: IN eAX,dx */
13762 uint8_t abInstr[1];
13763 if (pVmxTransient->cbExitInstr != sizeof(abInstr))
13764 return false;
13765
13766 /* Check that it is #GP(0). */
13767 if (pVmxTransient->uExitIntErrorCode != 0)
13768 return false;
13769
13770 /* Check magic and port. */
13771 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
13772 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
13773 if (pCtx->rax != UINT32_C(0x564d5868))
13774 return false;
13775 if (pCtx->dx != UINT32_C(0x5658))
13776 return false;
13777
13778 /* Flat ring-3 CS. */
13779 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
13780 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
13781 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
13782 if (pCtx->cs.Attr.n.u2Dpl != 3)
13783 return false;
13784 if (pCtx->cs.u64Base != 0)
13785 return false;
13786
13787 /* Check opcode. */
13788 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
13789 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
13790 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
13791 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
13792 if (RT_FAILURE(rc))
13793 return false;
13794 if (abInstr[0] != 0xed)
13795 return false;
13796
13797 return true;
13798}
13799
13800
13801/**
13802 * VM-exit exception handler for \#GP (General-protection exception).
13803 *
13804 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13805 */
13806static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13807{
13808 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13809 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
13810
13811 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13812 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13813 if (pVmcsInfo->RealMode.fRealOnV86Active)
13814 { /* likely */ }
13815 else
13816 {
13817#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13818 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
13819#endif
13820 /*
13821 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
13822 * executing a nested-guest, reflect #GP to the guest or nested-guest.
13823 */
13824 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13825 AssertRCReturn(rc, rc);
13826 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
13827 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
13828
13829 if ( pVmxTransient->fIsNestedGuest
13830 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
13831 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
13832 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13833 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13834 else
13835 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
13836 return rc;
13837 }
13838
13839 Assert(CPUMIsGuestInRealModeEx(pCtx));
13840 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
13841 Assert(!pVmxTransient->fIsNestedGuest);
13842
13843 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
13844 AssertRCReturn(rc, rc);
13845
13846 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
13847 if (rcStrict == VINF_SUCCESS)
13848 {
13849 if (!CPUMIsGuestInRealModeEx(pCtx))
13850 {
13851 /*
13852 * The guest is no longer in real-mode, check if we can continue executing the
13853 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
13854 */
13855 pVmcsInfo->RealMode.fRealOnV86Active = false;
13856 if (HMCanExecuteVmxGuest(pVCpu->pVMR0, pVCpu, pCtx))
13857 {
13858 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
13859 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13860 }
13861 else
13862 {
13863 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
13864 rcStrict = VINF_EM_RESCHEDULE;
13865 }
13866 }
13867 else
13868 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
13869 }
13870 else if (rcStrict == VINF_IEM_RAISED_XCPT)
13871 {
13872 rcStrict = VINF_SUCCESS;
13873 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
13874 }
13875 return VBOXSTRICTRC_VAL(rcStrict);
13876}
13877
13878
13879/**
13880 * VM-exit exception handler wrapper for all other exceptions that are not handled
13881 * by a specific handler.
13882 *
13883 * This simply re-injects the exception back into the VM without any special
13884 * processing.
13885 *
13886 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
13887 */
13888static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13889{
13890 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
13891
13892#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13893 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
13894 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
13895 ("uVector=%#x u32XcptBitmap=%#X32\n",
13896 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
13897 NOREF(pVmcsInfo);
13898#endif
13899
13900 /*
13901 * Re-inject the exception into the guest. This cannot be a double-fault condition which
13902 * would have been handled while checking exits due to event delivery.
13903 */
13904 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13905
13906#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
13907 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
13908 AssertRCReturn(rc, rc);
13909 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
13910#endif
13911
13912#ifdef VBOX_WITH_STATISTICS
13913 switch (uVector)
13914 {
13915 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
13916 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
13917 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
13918 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13919 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
13920 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
13921 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
13922 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
13923 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
13924 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
13925 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
13926 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
13927 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
13928 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
13929 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
13930 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
13931 default:
13932 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
13933 break;
13934 }
13935#endif
13936
13937 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
13938 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
13939 NOREF(uVector);
13940
13941 /* Re-inject the original exception into the guest. */
13942 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
13943 pVmxTransient->cbExitInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
13944 return VINF_SUCCESS;
13945}
13946
13947
13948/**
13949 * VM-exit exception handler for all exceptions (except NMIs!).
13950 *
13951 * @remarks This may be called for both guests and nested-guests. Take care to not
13952 * make assumptions and avoid doing anything that is not relevant when
13953 * executing a nested-guest (e.g., Mesa driver hacks).
13954 */
13955static VBOXSTRICTRC hmR0VmxExitXcpt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
13956{
13957 HMVMX_ASSERT_READ(pVmxTransient, HMVMX_READ_XCPT_INFO);
13958
13959 /*
13960 * If this VM-exit occurred while delivering an event through the guest IDT, take
13961 * action based on the return code and additional hints (e.g. for page-faults)
13962 * that will be updated in the VMX transient structure.
13963 */
13964 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
13965 if (rcStrict == VINF_SUCCESS)
13966 {
13967 /*
13968 * If an exception caused a VM-exit due to delivery of an event, the original
13969 * event may have to be re-injected into the guest. We shall reinject it and
13970 * continue guest execution. However, page-fault is a complicated case and
13971 * needs additional processing done in hmR0VmxExitXcptPF().
13972 */
13973 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
13974 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13975 if ( !pVCpu->hm.s.Event.fPending
13976 || uVector == X86_XCPT_PF)
13977 {
13978 switch (uVector)
13979 {
13980 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
13981 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
13982 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
13983 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
13984 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
13985 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
13986 default:
13987 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
13988 }
13989 }
13990 /* else: inject pending event before resuming guest execution. */
13991 }
13992 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
13993 {
13994 Assert(pVCpu->hm.s.Event.fPending);
13995 rcStrict = VINF_SUCCESS;
13996 }
13997
13998 return rcStrict;
13999}
14000/** @} */
14001
14002
14003/** @name VM-exit handlers.
14004 * @{
14005 */
14006/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14007/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14008/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14009
14010/**
14011 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14012 */
14013HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14014{
14015 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14016 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14017 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14018 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14019 return VINF_SUCCESS;
14020 return VINF_EM_RAW_INTERRUPT;
14021}
14022
14023
14024/**
14025 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14026 * VM-exit.
14027 */
14028HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14029{
14030 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14031 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14032
14033 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14034
14035 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14036 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14037 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14038
14039 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14040 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14041 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14042 NOREF(pVmcsInfo);
14043
14044 VBOXSTRICTRC rcStrict;
14045 switch (uExitIntType)
14046 {
14047 /*
14048 * Host physical NMIs:
14049 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14050 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14051 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14052 *
14053 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14054 * See Intel spec. 27.5.5 "Updating Non-Register State".
14055 */
14056 case VMX_EXIT_INT_INFO_TYPE_NMI:
14057 {
14058 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14059 break;
14060 }
14061
14062 /*
14063 * Privileged software exceptions (#DB from ICEBP),
14064 * Software exceptions (#BP and #OF),
14065 * Hardware exceptions:
14066 * Process the required exceptions and resume guest execution if possible.
14067 */
14068 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14069 Assert(uVector == X86_XCPT_DB);
14070 RT_FALL_THRU();
14071 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14072 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14073 RT_FALL_THRU();
14074 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14075 {
14076 NOREF(uVector);
14077 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14078 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14079 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14080 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14081
14082 rcStrict = hmR0VmxExitXcpt(pVCpu, pVmxTransient);
14083 break;
14084 }
14085
14086 default:
14087 {
14088 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14089 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14090 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14091 break;
14092 }
14093 }
14094
14095 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14096 return rcStrict;
14097}
14098
14099
14100/**
14101 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14102 */
14103HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14104{
14105 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14106
14107 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14108 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14109 hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14110
14111 /* Evaluate and deliver pending events and resume guest execution. */
14112 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14113 return VINF_SUCCESS;
14114}
14115
14116
14117/**
14118 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
14119 */
14120HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14121{
14122 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14123
14124 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14125 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
14126 {
14127 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
14128 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14129 }
14130
14131 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
14132
14133 /*
14134 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
14135 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
14136 */
14137 uint32_t fIntrState;
14138 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
14139 AssertRC(rc);
14140 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
14141 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
14142 {
14143 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
14144 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
14145
14146 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
14147 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
14148 AssertRC(rc);
14149 }
14150
14151 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
14152 hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
14153
14154 /* Evaluate and deliver pending events and resume guest execution. */
14155 return VINF_SUCCESS;
14156}
14157
14158
14159/**
14160 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
14161 */
14162HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14163{
14164 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14165 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14166}
14167
14168
14169/**
14170 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
14171 */
14172HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14173{
14174 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14175 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14176}
14177
14178
14179/**
14180 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
14181 */
14182HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14183{
14184 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14185
14186 /*
14187 * Get the state we need and update the exit history entry.
14188 */
14189 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14190 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14191
14192 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14193 AssertRCReturn(rc, rc);
14194
14195 VBOXSTRICTRC rcStrict;
14196 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
14197 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
14198 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
14199 if (!pExitRec)
14200 {
14201 /*
14202 * Regular CPUID instruction execution.
14203 */
14204 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbExitInstr);
14205 if (rcStrict == VINF_SUCCESS)
14206 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14207 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14208 {
14209 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14210 rcStrict = VINF_SUCCESS;
14211 }
14212 }
14213 else
14214 {
14215 /*
14216 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
14217 */
14218 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14219 AssertRCReturn(rc2, rc2);
14220
14221 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
14222 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
14223
14224 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
14225 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14226
14227 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
14228 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
14229 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
14230 }
14231 return rcStrict;
14232}
14233
14234
14235/**
14236 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
14237 */
14238HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14239{
14240 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14241
14242 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14243 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
14244 AssertRCReturn(rc, rc);
14245
14246 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
14247 return VINF_EM_RAW_EMULATE_INSTR;
14248
14249 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
14250 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14251}
14252
14253
14254/**
14255 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
14256 */
14257HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14258{
14259 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14260
14261 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14262 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14263 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14264 AssertRCReturn(rc, rc);
14265
14266 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbExitInstr);
14267 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14268 {
14269 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14270 we must reset offsetting on VM-entry. See @bugref{6634}. */
14271 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14272 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14273 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14274 }
14275 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14276 {
14277 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14278 rcStrict = VINF_SUCCESS;
14279 }
14280 return rcStrict;
14281}
14282
14283
14284/**
14285 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
14286 */
14287HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14288{
14289 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14290
14291 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14292 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14293 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
14294 AssertRCReturn(rc, rc);
14295
14296 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbExitInstr);
14297 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14298 {
14299 /* If we get a spurious VM-exit when TSC offsetting is enabled,
14300 we must reset offsetting on VM-reentry. See @bugref{6634}. */
14301 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
14302 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14303 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14304 }
14305 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14306 {
14307 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14308 rcStrict = VINF_SUCCESS;
14309 }
14310 return rcStrict;
14311}
14312
14313
14314/**
14315 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
14316 */
14317HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14318{
14319 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14320
14321 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14322 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
14323 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
14324 AssertRCReturn(rc, rc);
14325
14326 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14327 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
14328 if (RT_LIKELY(rc == VINF_SUCCESS))
14329 {
14330 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14331 Assert(pVmxTransient->cbExitInstr == 2);
14332 }
14333 else
14334 {
14335 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
14336 rc = VERR_EM_INTERPRETER;
14337 }
14338 return rc;
14339}
14340
14341
14342/**
14343 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
14344 */
14345HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14346{
14347 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14348
14349 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
14350 if (EMAreHypercallInstructionsEnabled(pVCpu))
14351 {
14352 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14353 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
14354 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
14355 AssertRCReturn(rc, rc);
14356
14357 /* Perform the hypercall. */
14358 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
14359 if (rcStrict == VINF_SUCCESS)
14360 {
14361 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14362 AssertRCReturn(rc, rc);
14363 }
14364 else
14365 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
14366 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
14367 || RT_FAILURE(rcStrict));
14368
14369 /* If the hypercall changes anything other than guest's general-purpose registers,
14370 we would need to reload the guest changed bits here before VM-entry. */
14371 }
14372 else
14373 Log4Func(("Hypercalls not enabled\n"));
14374
14375 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
14376 if (RT_FAILURE(rcStrict))
14377 {
14378 hmR0VmxSetPendingXcptUD(pVCpu);
14379 rcStrict = VINF_SUCCESS;
14380 }
14381
14382 return rcStrict;
14383}
14384
14385
14386/**
14387 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
14388 */
14389HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14390{
14391 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14392 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
14393
14394 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14395 hmR0VmxReadExitQualVmcs(pVmxTransient);
14396 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14397 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14398 AssertRCReturn(rc, rc);
14399
14400 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->uExitQual);
14401
14402 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
14403 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14404 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14405 {
14406 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14407 rcStrict = VINF_SUCCESS;
14408 }
14409 else
14410 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
14411 VBOXSTRICTRC_VAL(rcStrict)));
14412 return rcStrict;
14413}
14414
14415
14416/**
14417 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
14418 */
14419HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14420{
14421 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14422
14423 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14424 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14425 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
14426 AssertRCReturn(rc, rc);
14427
14428 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbExitInstr);
14429 if (rcStrict == VINF_SUCCESS)
14430 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14431 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14432 {
14433 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14434 rcStrict = VINF_SUCCESS;
14435 }
14436
14437 return rcStrict;
14438}
14439
14440
14441/**
14442 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
14443 */
14444HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14445{
14446 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14447
14448 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14449 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14450 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
14451 AssertRCReturn(rc, rc);
14452
14453 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbExitInstr);
14454 if (RT_SUCCESS(rcStrict))
14455 {
14456 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14457 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
14458 rcStrict = VINF_SUCCESS;
14459 }
14460
14461 return rcStrict;
14462}
14463
14464
14465/**
14466 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
14467 * VM-exit.
14468 */
14469HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14470{
14471 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14472 return VINF_EM_RESET;
14473}
14474
14475
14476/**
14477 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
14478 */
14479HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14480{
14481 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14482
14483 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14484 AssertRCReturn(rc, rc);
14485
14486 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
14487 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
14488 rc = VINF_SUCCESS;
14489 else
14490 rc = VINF_EM_HALT;
14491
14492 if (rc != VINF_SUCCESS)
14493 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
14494 return rc;
14495}
14496
14497
14498/**
14499 * VM-exit handler for instructions that result in a \#UD exception delivered to
14500 * the guest.
14501 */
14502HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14503{
14504 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14505 hmR0VmxSetPendingXcptUD(pVCpu);
14506 return VINF_SUCCESS;
14507}
14508
14509
14510/**
14511 * VM-exit handler for expiry of the VMX-preemption timer.
14512 */
14513HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14514{
14515 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14516
14517 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
14518 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14519
14520 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
14521 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14522 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
14523 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
14524 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
14525}
14526
14527
14528/**
14529 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
14530 */
14531HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14532{
14533 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14534
14535 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14536 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14537 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
14538 AssertRCReturn(rc, rc);
14539
14540 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbExitInstr);
14541 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
14542 : HM_CHANGED_RAISED_XCPT_MASK);
14543
14544 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14545 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
14546
14547 return rcStrict;
14548}
14549
14550
14551/**
14552 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
14553 */
14554HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14555{
14556 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14557
14558#if 1
14559 /** @todo Use VM-exit instruction information. */
14560 return VERR_EM_INTERPRETER;
14561#else
14562 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14563 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
14564 hmR0VmxReadExitQualVmcs(pVmxTransient);
14565 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
14566 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
14567 AssertRCReturn(rc, rc);
14568
14569 /* Paranoia. Ensure this has a memory operand. */
14570 Assert(!pVmxTransient->ExitInstrInfo.Inv.u1Cleared0);
14571
14572 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
14573 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14574 uint64_t const uType = CPUMIsGuestIn64BitCode(pVCpu) ? pVCpu->cpum.GstCtx.aGRegs[iGReg].u64
14575 : pVCpu->cpum.GstCtx.aGRegs[iGReg].u32;
14576
14577 RTGCPTR GCPtrDesc;
14578 HMVMX_DECODE_MEM_OPERAND(pVCpu, pVmxTransient->ExitInstrInfo.u, pVmxTransient->uExitQual, VMXMEMACCESS_READ, &GCPtrDesc);
14579
14580 VBOXSTRICTRC rcStrict = IEMExecDecodedInvpcid(pVCpu, pVmxTransient->cbExitInstr, pVmxTransient->ExitInstrInfo.Inv.iSegReg,
14581 GCPtrDesc, uType);
14582 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
14583 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14584 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14585 {
14586 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14587 rcStrict = VINF_SUCCESS;
14588 }
14589 return rcStrict;
14590#endif
14591}
14592
14593
14594/**
14595 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
14596 * VM-exit.
14597 */
14598HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14599{
14600 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14601 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14602 AssertRCReturn(rc, rc);
14603
14604 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
14605 if (RT_FAILURE(rc))
14606 return rc;
14607
14608 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
14609 NOREF(uInvalidReason);
14610
14611#ifdef VBOX_STRICT
14612 uint32_t fIntrState;
14613 uint64_t u64Val;
14614 hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
14615 hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
14616 hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
14617
14618 Log4(("uInvalidReason %u\n", uInvalidReason));
14619 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
14620 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
14621 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
14622
14623 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState); AssertRC(rc);
14624 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
14625 rc = VMXReadVmcsNw(VMX_VMCS_GUEST_CR0, &u64Val); AssertRC(rc);
14626 Log4(("VMX_VMCS_GUEST_CR0 %#RX64\n", u64Val));
14627 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_MASK, &u64Val); AssertRC(rc);
14628 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RX64\n", u64Val));
14629 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Val); AssertRC(rc);
14630 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14631 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_MASK, &u64Val); AssertRC(rc);
14632 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RX64\n", u64Val));
14633 rc = VMXReadVmcsNw(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Val); AssertRC(rc);
14634 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RX64\n", u64Val));
14635 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
14636 {
14637 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
14638 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
14639 }
14640 hmR0DumpRegs(pVCpu, HM_DUMP_REG_FLAGS_ALL);
14641#endif
14642
14643 return VERR_VMX_INVALID_GUEST_STATE;
14644}
14645
14646/**
14647 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
14648 */
14649HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14650{
14651 /*
14652 * Cumulative notes of all recognized but unexpected VM-exits.
14653 *
14654 * 1. This does -not- cover scenarios like a page-fault VM-exit occurring when
14655 * nested-paging is used.
14656 *
14657 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
14658 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
14659 * this function (and thereby stop VM execution) for handling such instructions.
14660 *
14661 *
14662 * VMX_EXIT_INIT_SIGNAL:
14663 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
14664 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
14665 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
14666 *
14667 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
14668 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
14669 * See Intel spec. "23.8 Restrictions on VMX operation".
14670 *
14671 * VMX_EXIT_SIPI:
14672 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
14673 * activity state is used. We don't make use of it as our guests don't have direct
14674 * access to the host local APIC.
14675 *
14676 * See Intel spec. 25.3 "Other Causes of VM-exits".
14677 *
14678 * VMX_EXIT_IO_SMI:
14679 * VMX_EXIT_SMI:
14680 * This can only happen if we support dual-monitor treatment of SMI, which can be
14681 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
14682 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
14683 * VMX root mode or receive an SMI. If we get here, something funny is going on.
14684 *
14685 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
14686 * See Intel spec. 25.3 "Other Causes of VM-Exits"
14687 *
14688 * VMX_EXIT_ERR_MSR_LOAD:
14689 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
14690 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
14691 * execution.
14692 *
14693 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
14694 *
14695 * VMX_EXIT_ERR_MACHINE_CHECK:
14696 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
14697 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
14698 * #MC exception abort class exception is raised. We thus cannot assume a
14699 * reasonable chance of continuing any sort of execution and we bail.
14700 *
14701 * See Intel spec. 15.1 "Machine-check Architecture".
14702 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
14703 *
14704 * VMX_EXIT_PML_FULL:
14705 * VMX_EXIT_VIRTUALIZED_EOI:
14706 * VMX_EXIT_APIC_WRITE:
14707 * We do not currently support any of these features and thus they are all unexpected
14708 * VM-exits.
14709 *
14710 * VMX_EXIT_GDTR_IDTR_ACCESS:
14711 * VMX_EXIT_LDTR_TR_ACCESS:
14712 * VMX_EXIT_RDRAND:
14713 * VMX_EXIT_RSM:
14714 * VMX_EXIT_VMFUNC:
14715 * VMX_EXIT_ENCLS:
14716 * VMX_EXIT_RDSEED:
14717 * VMX_EXIT_XSAVES:
14718 * VMX_EXIT_XRSTORS:
14719 * VMX_EXIT_UMWAIT:
14720 * VMX_EXIT_TPAUSE:
14721 * These VM-exits are -not- caused unconditionally by execution of the corresponding
14722 * instruction. Any VM-exit for these instructions indicate a hardware problem,
14723 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
14724 *
14725 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
14726 */
14727 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14728 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
14729 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
14730}
14731
14732
14733/**
14734 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
14735 */
14736HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14737{
14738 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14739
14740 /** @todo Optimize this: We currently drag in the whole MSR state
14741 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14742 * MSRs required. That would require changes to IEM and possibly CPUM too.
14743 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14744 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14745 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14746 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14747 switch (idMsr)
14748 {
14749 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14750 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14751 }
14752
14753 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14754 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14755 AssertRCReturn(rc, rc);
14756
14757 Log4Func(("ecx=%#RX32\n", idMsr));
14758
14759#ifdef VBOX_STRICT
14760 Assert(!pVmxTransient->fIsNestedGuest);
14761 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
14762 {
14763 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
14764 && idMsr != MSR_K6_EFER)
14765 {
14766 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
14767 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14768 }
14769 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14770 {
14771 Assert(pVmcsInfo->pvMsrBitmap);
14772 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14773 if (fMsrpm & VMXMSRPM_ALLOW_RD)
14774 {
14775 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
14776 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14777 }
14778 }
14779 }
14780#endif
14781
14782 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbExitInstr);
14783 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
14784 if (rcStrict == VINF_SUCCESS)
14785 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14786 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14787 {
14788 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14789 rcStrict = VINF_SUCCESS;
14790 }
14791 else
14792 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14793
14794 return rcStrict;
14795}
14796
14797
14798/**
14799 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
14800 */
14801HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14802{
14803 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14804
14805 /** @todo Optimize this: We currently drag in the whole MSR state
14806 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
14807 * MSRs required. That would require changes to IEM and possibly CPUM too.
14808 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
14809 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
14810 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
14811
14812 /*
14813 * The FS and GS base MSRs are not part of the above all-MSRs mask.
14814 * Although we don't need to fetch the base as it will be overwritten shortly, while
14815 * loading guest-state we would also load the entire segment register including limit
14816 * and attributes and thus we need to load them here.
14817 */
14818 switch (idMsr)
14819 {
14820 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
14821 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
14822 }
14823
14824 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14825 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14826 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
14827 AssertRCReturn(rc, rc);
14828
14829 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
14830
14831 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbExitInstr);
14832 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
14833
14834 if (rcStrict == VINF_SUCCESS)
14835 {
14836 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14837
14838 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
14839 if ( idMsr == MSR_IA32_APICBASE
14840 || ( idMsr >= MSR_IA32_X2APIC_START
14841 && idMsr <= MSR_IA32_X2APIC_END))
14842 {
14843 /*
14844 * We've already saved the APIC related guest-state (TPR) in post-run phase.
14845 * When full APIC register virtualization is implemented we'll have to make
14846 * sure APIC state is saved from the VMCS before IEM changes it.
14847 */
14848 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
14849 }
14850 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
14851 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
14852 else if (idMsr == MSR_K6_EFER)
14853 {
14854 /*
14855 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
14856 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
14857 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
14858 */
14859 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
14860 }
14861
14862 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
14863 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
14864 {
14865 switch (idMsr)
14866 {
14867 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
14868 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
14869 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
14870 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
14871 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
14872 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
14873 default:
14874 {
14875 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14876 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
14877 else if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14878 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
14879 break;
14880 }
14881 }
14882 }
14883#ifdef VBOX_STRICT
14884 else
14885 {
14886 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
14887 switch (idMsr)
14888 {
14889 case MSR_IA32_SYSENTER_CS:
14890 case MSR_IA32_SYSENTER_EIP:
14891 case MSR_IA32_SYSENTER_ESP:
14892 case MSR_K8_FS_BASE:
14893 case MSR_K8_GS_BASE:
14894 {
14895 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
14896 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14897 }
14898
14899 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
14900 default:
14901 {
14902 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
14903 {
14904 /* EFER MSR writes are always intercepted. */
14905 if (idMsr != MSR_K6_EFER)
14906 {
14907 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
14908 idMsr));
14909 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14910 }
14911 }
14912
14913 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
14914 {
14915 Assert(pVmcsInfo->pvMsrBitmap);
14916 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
14917 if (fMsrpm & VMXMSRPM_ALLOW_WR)
14918 {
14919 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
14920 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
14921 }
14922 }
14923 break;
14924 }
14925 }
14926 }
14927#endif /* VBOX_STRICT */
14928 }
14929 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14930 {
14931 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14932 rcStrict = VINF_SUCCESS;
14933 }
14934 else
14935 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
14936
14937 return rcStrict;
14938}
14939
14940
14941/**
14942 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
14943 */
14944HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14945{
14946 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14947
14948 /** @todo The guest has likely hit a contended spinlock. We might want to
14949 * poke a schedule different guest VCPU. */
14950 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14951 if (RT_SUCCESS(rc))
14952 return VINF_EM_RAW_INTERRUPT;
14953
14954 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
14955 return rc;
14956}
14957
14958
14959/**
14960 * VM-exit handler for when the TPR value is lowered below the specified
14961 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
14962 */
14963HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14964{
14965 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14966 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
14967
14968 /*
14969 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
14970 * We'll re-evaluate pending interrupts and inject them before the next VM
14971 * entry so we can just continue execution here.
14972 */
14973 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
14974 return VINF_SUCCESS;
14975}
14976
14977
14978/**
14979 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
14980 * VM-exit.
14981 *
14982 * @retval VINF_SUCCESS when guest execution can continue.
14983 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
14984 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
14985 * incompatible guest state for VMX execution (real-on-v86 case).
14986 */
14987HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
14988{
14989 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14990 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
14991
14992 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14993 hmR0VmxReadExitQualVmcs(pVmxTransient);
14994 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14995
14996 VBOXSTRICTRC rcStrict;
14997 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
14998 uint64_t const uExitQual = pVmxTransient->uExitQual;
14999 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15000 switch (uAccessType)
15001 {
15002 /*
15003 * MOV to CRx.
15004 */
15005 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15006 {
15007 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15008 AssertRCReturn(rc, rc);
15009
15010 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15011 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15012 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15013 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15014
15015 /*
15016 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15017 * - When nested paging isn't used.
15018 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15019 * - We are executing in the VM debug loop.
15020 */
15021 Assert( iCrReg != 3
15022 || !pVM->hm.s.fNestedPaging
15023 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15024 || pVCpu->hm.s.fUsingDebugLoop);
15025
15026 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15027 Assert( iCrReg != 8
15028 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15029
15030 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15031 AssertMsg( rcStrict == VINF_SUCCESS
15032 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15033
15034 /*
15035 * This is a kludge for handling switches back to real mode when we try to use
15036 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15037 * deal with special selector values, so we have to return to ring-3 and run
15038 * there till the selector values are V86 mode compatible.
15039 *
15040 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15041 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15042 * this function.
15043 */
15044 if ( iCrReg == 0
15045 && rcStrict == VINF_SUCCESS
15046 && !pVM->hm.s.vmx.fUnrestrictedGuest
15047 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15048 && (uOldCr0 & X86_CR0_PE)
15049 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15050 {
15051 /** @todo Check selectors rather than returning all the time. */
15052 Assert(!pVmxTransient->fIsNestedGuest);
15053 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15054 rcStrict = VINF_EM_RESCHEDULE_REM;
15055 }
15056 break;
15057 }
15058
15059 /*
15060 * MOV from CRx.
15061 */
15062 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15063 {
15064 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15065 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15066
15067 /*
15068 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15069 * - When nested paging isn't used.
15070 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15071 * - We are executing in the VM debug loop.
15072 */
15073 Assert( iCrReg != 3
15074 || !pVM->hm.s.fNestedPaging
15075 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15076 || pVCpu->hm.s.fUsingDebugLoop);
15077
15078 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15079 Assert( iCrReg != 8
15080 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15081
15082 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
15083 break;
15084 }
15085
15086 /*
15087 * CLTS (Clear Task-Switch Flag in CR0).
15088 */
15089 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15090 {
15091 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbExitInstr);
15092 break;
15093 }
15094
15095 /*
15096 * LMSW (Load Machine-Status Word into CR0).
15097 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15098 */
15099 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15100 {
15101 RTGCPTR GCPtrEffDst;
15102 uint8_t const cbInstr = pVmxTransient->cbExitInstr;
15103 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15104 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15105 if (fMemOperand)
15106 {
15107 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
15108 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15109 }
15110 else
15111 GCPtrEffDst = NIL_RTGCPTR;
15112 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15113 break;
15114 }
15115
15116 default:
15117 {
15118 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15119 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15120 }
15121 }
15122
15123 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15124 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15125 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15126
15127 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15128 NOREF(pVM);
15129 return rcStrict;
15130}
15131
15132
15133/**
15134 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15135 * VM-exit.
15136 */
15137HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15138{
15139 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15140 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
15141
15142 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15143 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15144 hmR0VmxReadExitQualVmcs(pVmxTransient);
15145 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15146 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
15147 | CPUMCTX_EXTRN_EFER);
15148 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
15149 AssertRCReturn(rc, rc);
15150
15151 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
15152 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
15153 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
15154 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
15155 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
15156 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
15157 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
15158 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
15159
15160 /*
15161 * Update exit history to see if this exit can be optimized.
15162 */
15163 VBOXSTRICTRC rcStrict;
15164 PCEMEXITREC pExitRec = NULL;
15165 if ( !fGstStepping
15166 && !fDbgStepping)
15167 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15168 !fIOString
15169 ? !fIOWrite
15170 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
15171 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
15172 : !fIOWrite
15173 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
15174 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
15175 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15176 if (!pExitRec)
15177 {
15178 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
15179 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
15180
15181 uint32_t const cbValue = s_aIOSizes[uIOSize];
15182 uint32_t const cbInstr = pVmxTransient->cbExitInstr;
15183 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
15184 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15185 if (fIOString)
15186 {
15187 /*
15188 * INS/OUTS - I/O String instruction.
15189 *
15190 * Use instruction-information if available, otherwise fall back on
15191 * interpreting the instruction.
15192 */
15193 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15194 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
15195 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
15196 if (fInsOutsInfo)
15197 {
15198 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15199 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
15200 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
15201 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
15202 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
15203 if (fIOWrite)
15204 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
15205 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
15206 else
15207 {
15208 /*
15209 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
15210 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
15211 * See Intel Instruction spec. for "INS".
15212 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
15213 */
15214 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
15215 }
15216 }
15217 else
15218 rcStrict = IEMExecOne(pVCpu);
15219
15220 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15221 fUpdateRipAlready = true;
15222 }
15223 else
15224 {
15225 /*
15226 * IN/OUT - I/O instruction.
15227 */
15228 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
15229 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
15230 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
15231 if (fIOWrite)
15232 {
15233 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
15234 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
15235 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15236 && !pCtx->eflags.Bits.u1TF)
15237 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
15238 }
15239 else
15240 {
15241 uint32_t u32Result = 0;
15242 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
15243 if (IOM_SUCCESS(rcStrict))
15244 {
15245 /* Save result of I/O IN instr. in AL/AX/EAX. */
15246 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
15247 }
15248 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15249 && !pCtx->eflags.Bits.u1TF)
15250 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
15251 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
15252 }
15253 }
15254
15255 if (IOM_SUCCESS(rcStrict))
15256 {
15257 if (!fUpdateRipAlready)
15258 {
15259 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
15260 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
15261 }
15262
15263 /*
15264 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
15265 * while booting Fedora 17 64-bit guest.
15266 *
15267 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
15268 */
15269 if (fIOString)
15270 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
15271
15272 /*
15273 * If any I/O breakpoints are armed, we need to check if one triggered
15274 * and take appropriate action.
15275 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
15276 */
15277 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
15278 AssertRCReturn(rc, rc);
15279
15280 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
15281 * execution engines about whether hyper BPs and such are pending. */
15282 uint32_t const uDr7 = pCtx->dr[7];
15283 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
15284 && X86_DR7_ANY_RW_IO(uDr7)
15285 && (pCtx->cr4 & X86_CR4_DE))
15286 || DBGFBpIsHwIoArmed(pVM)))
15287 {
15288 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
15289
15290 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
15291 VMMRZCallRing3Disable(pVCpu);
15292 HM_DISABLE_PREEMPT(pVCpu);
15293
15294 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
15295
15296 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
15297 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
15298 {
15299 /* Raise #DB. */
15300 if (fIsGuestDbgActive)
15301 ASMSetDR6(pCtx->dr[6]);
15302 if (pCtx->dr[7] != uDr7)
15303 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
15304
15305 hmR0VmxSetPendingXcptDB(pVCpu);
15306 }
15307 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
15308 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
15309 else if ( rcStrict2 != VINF_SUCCESS
15310 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
15311 rcStrict = rcStrict2;
15312 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
15313
15314 HM_RESTORE_PREEMPT();
15315 VMMRZCallRing3Enable(pVCpu);
15316 }
15317 }
15318
15319#ifdef VBOX_STRICT
15320 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
15321 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
15322 Assert(!fIOWrite);
15323 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
15324 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
15325 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
15326 Assert(fIOWrite);
15327 else
15328 {
15329# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
15330 * statuses, that the VMM device and some others may return. See
15331 * IOM_SUCCESS() for guidance. */
15332 AssertMsg( RT_FAILURE(rcStrict)
15333 || rcStrict == VINF_SUCCESS
15334 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
15335 || rcStrict == VINF_EM_DBG_BREAKPOINT
15336 || rcStrict == VINF_EM_RAW_GUEST_TRAP
15337 || rcStrict == VINF_EM_RAW_TO_R3
15338 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15339# endif
15340 }
15341#endif
15342 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
15343 }
15344 else
15345 {
15346 /*
15347 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15348 */
15349 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15350 AssertRCReturn(rc2, rc2);
15351 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
15352 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
15353 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
15354 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15355 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
15356 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
15357
15358 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15359 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15360
15361 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15362 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15363 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15364 }
15365 return rcStrict;
15366}
15367
15368
15369/**
15370 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
15371 * VM-exit.
15372 */
15373HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15374{
15375 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15376
15377 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
15378 hmR0VmxReadExitQualVmcs(pVmxTransient);
15379 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
15380 {
15381 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15382 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
15383 {
15384 uint32_t uErrCode;
15385 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
15386 {
15387 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15388 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
15389 }
15390 else
15391 uErrCode = 0;
15392
15393 RTGCUINTPTR GCPtrFaultAddress;
15394 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
15395 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
15396 else
15397 GCPtrFaultAddress = 0;
15398
15399 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15400
15401 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
15402 pVmxTransient->cbExitInstr, uErrCode, GCPtrFaultAddress);
15403
15404 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
15405 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
15406 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15407 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15408 }
15409 }
15410
15411 /* Fall back to the interpreter to emulate the task-switch. */
15412 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
15413 return VERR_EM_INTERPRETER;
15414}
15415
15416
15417/**
15418 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
15419 */
15420HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15421{
15422 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15423
15424 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15425 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
15426 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15427 AssertRC(rc);
15428 return VINF_EM_DBG_STEPPED;
15429}
15430
15431
15432/**
15433 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
15434 */
15435HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15436{
15437 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15438 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
15439
15440 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15441 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15442 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15443 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15444 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15445
15446 /*
15447 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15448 */
15449 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15450 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15451 {
15452 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
15453 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
15454 {
15455 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15456 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15457 }
15458 }
15459 else
15460 {
15461 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15462 return rcStrict;
15463 }
15464
15465 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
15466 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15467 hmR0VmxReadExitQualVmcs(pVmxTransient);
15468 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15469 AssertRCReturn(rc, rc);
15470
15471 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
15472 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
15473 switch (uAccessType)
15474 {
15475 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
15476 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
15477 {
15478 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
15479 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
15480 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
15481
15482 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
15483 GCPhys &= PAGE_BASE_GC_MASK;
15484 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
15485 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
15486 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
15487
15488 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15489 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15490 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
15491 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
15492 CPUMCTX2CORE(pCtx), GCPhys);
15493 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15494 if ( rcStrict == VINF_SUCCESS
15495 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15496 || rcStrict == VERR_PAGE_NOT_PRESENT)
15497 {
15498 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15499 | HM_CHANGED_GUEST_APIC_TPR);
15500 rcStrict = VINF_SUCCESS;
15501 }
15502 break;
15503 }
15504
15505 default:
15506 {
15507 Log4Func(("uAccessType=%#x\n", uAccessType));
15508 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
15509 break;
15510 }
15511 }
15512
15513 if (rcStrict != VINF_SUCCESS)
15514 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
15515 return rcStrict;
15516}
15517
15518
15519/**
15520 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
15521 * VM-exit.
15522 */
15523HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15524{
15525 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15526 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15527
15528 /* We might get this VM-exit if the nested-guest is not intercepting MOV DRx accesses. */
15529 if (!pVmxTransient->fIsNestedGuest)
15530 {
15531 /* We should -not- get this VM-exit if the guest's debug registers were active. */
15532 if (pVmxTransient->fWasGuestDebugStateActive)
15533 {
15534 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
15535 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15536 }
15537
15538 if ( !pVCpu->hm.s.fSingleInstruction
15539 && !pVmxTransient->fWasHyperDebugStateActive)
15540 {
15541 Assert(!DBGFIsStepping(pVCpu));
15542 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
15543
15544 /* Don't intercept MOV DRx any more. */
15545 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
15546 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
15547 AssertRC(rc);
15548
15549 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
15550 VMMRZCallRing3Disable(pVCpu);
15551 HM_DISABLE_PREEMPT(pVCpu);
15552
15553 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
15554 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
15555 Assert(CPUMIsGuestDebugStateActive(pVCpu));
15556
15557 HM_RESTORE_PREEMPT();
15558 VMMRZCallRing3Enable(pVCpu);
15559
15560#ifdef VBOX_WITH_STATISTICS
15561 hmR0VmxReadExitQualVmcs(pVmxTransient);
15562 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15563 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15564 else
15565 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15566#endif
15567 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
15568 return VINF_SUCCESS;
15569 }
15570 }
15571
15572 /*
15573 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
15574 * The EFER MSR is always up-to-date.
15575 * Update the segment registers and DR7 from the CPU.
15576 */
15577 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15578 hmR0VmxReadExitQualVmcs(pVmxTransient);
15579 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
15580 AssertRCReturn(rc, rc);
15581 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
15582
15583 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15584 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
15585 {
15586 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15587 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
15588 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
15589 if (RT_SUCCESS(rc))
15590 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
15591 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
15592 }
15593 else
15594 {
15595 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
15596 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
15597 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
15598 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
15599 }
15600
15601 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
15602 if (RT_SUCCESS(rc))
15603 {
15604 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15605 AssertRCReturn(rc2, rc2);
15606 return VINF_SUCCESS;
15607 }
15608 return rc;
15609}
15610
15611
15612/**
15613 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
15614 * Conditional VM-exit.
15615 */
15616HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15617{
15618 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15619 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15620
15621 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15622 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15623 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15624 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15625 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15626
15627 /*
15628 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15629 */
15630 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15631 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15632 {
15633 /*
15634 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
15635 * instruction emulation to inject the original event. Otherwise, injecting the original event
15636 * using hardware-assisted VMX would trigger the same EPT misconfig VM-exit again.
15637 */
15638 if (!pVCpu->hm.s.Event.fPending)
15639 { /* likely */ }
15640 else
15641 {
15642 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
15643#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15644 /** @todo NSTVMX: Think about how this should be handled. */
15645 if (pVmxTransient->fIsNestedGuest)
15646 return VERR_VMX_IPE_3;
15647#endif
15648 return VINF_EM_RAW_INJECT_TRPM_EVENT;
15649 }
15650 }
15651 else
15652 {
15653 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15654 return rcStrict;
15655 }
15656
15657 /*
15658 * Get sufficient state and update the exit history entry.
15659 */
15660 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15661 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15662 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15663 AssertRCReturn(rc, rc);
15664
15665 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15666 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15667 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
15668 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15669 if (!pExitRec)
15670 {
15671 /*
15672 * If we succeed, resume guest execution.
15673 * If we fail in interpreting the instruction because we couldn't get the guest physical address
15674 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
15675 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
15676 * weird case. See @bugref{6043}.
15677 */
15678 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15679 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15680 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
15681 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
15682 if ( rcStrict == VINF_SUCCESS
15683 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15684 || rcStrict == VERR_PAGE_NOT_PRESENT)
15685 {
15686 /* Successfully handled MMIO operation. */
15687 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
15688 | HM_CHANGED_GUEST_APIC_TPR);
15689 rcStrict = VINF_SUCCESS;
15690 }
15691 }
15692 else
15693 {
15694 /*
15695 * Frequent exit or something needing probing. Call EMHistoryExec.
15696 */
15697 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
15698 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
15699
15700 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15701 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15702
15703 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15704 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15705 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15706 }
15707 return rcStrict;
15708}
15709
15710
15711/**
15712 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
15713 * VM-exit.
15714 */
15715HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15716{
15717 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15718 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
15719
15720 hmR0VmxReadExitQualVmcs(pVmxTransient);
15721 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
15722 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
15723 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15724 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
15725 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
15726
15727 /*
15728 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
15729 */
15730 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
15731 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15732 {
15733 /*
15734 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
15735 * we shall resolve the nested #PF and re-inject the original event.
15736 */
15737 if (pVCpu->hm.s.Event.fPending)
15738 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
15739 }
15740 else
15741 {
15742 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
15743 return rcStrict;
15744 }
15745
15746 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15747 hmR0VmxReadGuestPhysicalAddrVmcs(pVmxTransient);
15748 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15749 AssertRCReturn(rc, rc);
15750
15751 RTGCPHYS const GCPhys = pVmxTransient->uGuestPhysicalAddr;
15752 uint64_t const uExitQual = pVmxTransient->uExitQual;
15753 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", uExitQual));
15754
15755 RTGCUINT uErrorCode = 0;
15756 if (uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
15757 uErrorCode |= X86_TRAP_PF_ID;
15758 if (uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
15759 uErrorCode |= X86_TRAP_PF_RW;
15760 if (uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
15761 uErrorCode |= X86_TRAP_PF_P;
15762
15763 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
15764 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15765 Log4Func(("at %#RX64 (%#RX64 errcode=%#x) cs:rip=%#04x:%#RX64\n", GCPhys, uExitQual, uErrorCode, pCtx->cs.Sel, pCtx->rip));
15766
15767 /*
15768 * Handle the pagefault trap for the nested shadow table.
15769 */
15770 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
15771 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
15772 TRPMResetTrap(pVCpu);
15773
15774 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
15775 if ( rcStrict == VINF_SUCCESS
15776 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
15777 || rcStrict == VERR_PAGE_NOT_PRESENT)
15778 {
15779 /* Successfully synced our nested page tables. */
15780 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
15781 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
15782 return VINF_SUCCESS;
15783 }
15784
15785 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15786 return rcStrict;
15787}
15788
15789
15790#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
15791/**
15792 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
15793 */
15794HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15795{
15796 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15797
15798 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15799 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15800 hmR0VmxReadExitQualVmcs(pVmxTransient);
15801 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15802 | CPUMCTX_EXTRN_HWVIRT
15803 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15804 AssertRCReturn(rc, rc);
15805
15806 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15807
15808 VMXVEXITINFO ExitInfo;
15809 RT_ZERO(ExitInfo);
15810 ExitInfo.uReason = pVmxTransient->uExitReason;
15811 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15812 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15813 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15814 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15815
15816 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
15817 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15818 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15819 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15820 {
15821 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15822 rcStrict = VINF_SUCCESS;
15823 }
15824 return rcStrict;
15825}
15826
15827
15828/**
15829 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
15830 */
15831HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15832{
15833 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15834
15835 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
15836 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15837 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15838 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15839 AssertRCReturn(rc, rc);
15840
15841 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15842
15843 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15844 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMLAUNCH);
15845 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15846 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15847 {
15848 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15849 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15850 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15851 }
15852 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15853 return rcStrict;
15854}
15855
15856
15857/**
15858 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
15859 */
15860HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15861{
15862 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15863
15864 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15865 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15866 hmR0VmxReadExitQualVmcs(pVmxTransient);
15867 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15868 | CPUMCTX_EXTRN_HWVIRT
15869 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15870 AssertRCReturn(rc, rc);
15871
15872 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15873
15874 VMXVEXITINFO ExitInfo;
15875 RT_ZERO(ExitInfo);
15876 ExitInfo.uReason = pVmxTransient->uExitReason;
15877 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15878 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15879 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15880 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
15881
15882 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
15883 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15884 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
15885 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15886 {
15887 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15888 rcStrict = VINF_SUCCESS;
15889 }
15890 return rcStrict;
15891}
15892
15893
15894/**
15895 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
15896 */
15897HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15898{
15899 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15900
15901 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15902 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15903 hmR0VmxReadExitQualVmcs(pVmxTransient);
15904 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15905 | CPUMCTX_EXTRN_HWVIRT
15906 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15907 AssertRCReturn(rc, rc);
15908
15909 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15910
15911 VMXVEXITINFO ExitInfo;
15912 RT_ZERO(ExitInfo);
15913 ExitInfo.uReason = pVmxTransient->uExitReason;
15914 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15915 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15916 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15917 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15918
15919 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
15920 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15921 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15922 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15923 {
15924 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15925 rcStrict = VINF_SUCCESS;
15926 }
15927 return rcStrict;
15928}
15929
15930
15931/**
15932 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
15933 */
15934HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15935{
15936 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15937
15938 /*
15939 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
15940 * thus might not need to import the shadow VMCS state, it's safer just in case
15941 * code elsewhere dares look at unsynced VMCS fields.
15942 */
15943 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15944 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
15945 hmR0VmxReadExitQualVmcs(pVmxTransient);
15946 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
15947 | CPUMCTX_EXTRN_HWVIRT
15948 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15949 AssertRCReturn(rc, rc);
15950
15951 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15952
15953 VMXVEXITINFO ExitInfo;
15954 RT_ZERO(ExitInfo);
15955 ExitInfo.uReason = pVmxTransient->uExitReason;
15956 ExitInfo.u64Qual = pVmxTransient->uExitQual;
15957 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
15958 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
15959 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
15960 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
15961
15962 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
15963 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15964 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15965 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15966 {
15967 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15968 rcStrict = VINF_SUCCESS;
15969 }
15970 return rcStrict;
15971}
15972
15973
15974/**
15975 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
15976 */
15977HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
15978{
15979 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15980
15981 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
15982 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
15983 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15984 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15985 AssertRCReturn(rc, rc);
15986
15987 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
15988
15989 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
15990 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbExitInstr, VMXINSTRID_VMRESUME);
15991 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
15992 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15993 {
15994 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15995 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
15996 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
15997 }
15998 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15999 return rcStrict;
16000}
16001
16002
16003/**
16004 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16005 */
16006HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16007{
16008 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16009
16010 /*
16011 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16012 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16013 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16014 */
16015 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16016 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16017 hmR0VmxReadExitQualVmcs(pVmxTransient);
16018 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16019 | CPUMCTX_EXTRN_HWVIRT
16020 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16021 AssertRCReturn(rc, rc);
16022
16023 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16024
16025 VMXVEXITINFO ExitInfo;
16026 RT_ZERO(ExitInfo);
16027 ExitInfo.uReason = pVmxTransient->uExitReason;
16028 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16029 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16030 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16031 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16032 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16033
16034 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16035 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16036 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16037 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16038 {
16039 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16040 rcStrict = VINF_SUCCESS;
16041 }
16042 return rcStrict;
16043}
16044
16045
16046/**
16047 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16048 */
16049HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16050{
16051 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16052
16053 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16054 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16055 | CPUMCTX_EXTRN_HWVIRT
16056 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16057 AssertRCReturn(rc, rc);
16058
16059 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16060
16061 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbExitInstr);
16062 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16063 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16064 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16065 {
16066 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16067 rcStrict = VINF_SUCCESS;
16068 }
16069 return rcStrict;
16070}
16071
16072
16073/**
16074 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16075 */
16076HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16077{
16078 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16079
16080 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16081 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16082 hmR0VmxReadExitQualVmcs(pVmxTransient);
16083 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16084 | CPUMCTX_EXTRN_HWVIRT
16085 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16086 AssertRCReturn(rc, rc);
16087
16088 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16089
16090 VMXVEXITINFO ExitInfo;
16091 RT_ZERO(ExitInfo);
16092 ExitInfo.uReason = pVmxTransient->uExitReason;
16093 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16094 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16095 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16096 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16097
16098 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16099 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16100 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16101 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16102 {
16103 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16104 rcStrict = VINF_SUCCESS;
16105 }
16106 return rcStrict;
16107}
16108
16109
16110/**
16111 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16112 */
16113HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16114{
16115 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16116
16117 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16118 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16119 hmR0VmxReadExitQualVmcs(pVmxTransient);
16120 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16121 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16122 AssertRCReturn(rc, rc);
16123
16124 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16125
16126 VMXVEXITINFO ExitInfo;
16127 RT_ZERO(ExitInfo);
16128 ExitInfo.uReason = pVmxTransient->uExitReason;
16129 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16130 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16131 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16132 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16133
16134 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
16135 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16136 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16137 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16138 {
16139 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16140 rcStrict = VINF_SUCCESS;
16141 }
16142 return rcStrict;
16143}
16144#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
16145/** @} */
16146
16147
16148#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16149/** @name Nested-guest VM-exit handlers.
16150 * @{
16151 */
16152/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16153/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16154/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
16155
16156/**
16157 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
16158 * Conditional VM-exit.
16159 */
16160HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16161{
16162 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16163
16164 hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16165
16166 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
16167 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
16168 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
16169
16170 switch (uExitIntType)
16171 {
16172 /*
16173 * Physical NMIs:
16174 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
16175 */
16176 case VMX_EXIT_INT_INFO_TYPE_NMI:
16177 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
16178
16179 /*
16180 * Hardware exceptions,
16181 * Software exceptions,
16182 * Privileged software exceptions:
16183 * Figure out if the exception must be delivered to the guest or the nested-guest.
16184 */
16185 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
16186 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
16187 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
16188 {
16189 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16190 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16191 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16192 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16193
16194 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16195 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, pCtx, VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo),
16196 pVmxTransient->uExitIntErrorCode);
16197 if (fIntercept)
16198 {
16199 /* Exit qualification is required for debug and page-fault exceptions. */
16200 hmR0VmxReadExitQualVmcs(pVmxTransient);
16201
16202 /*
16203 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
16204 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
16205 * length. However, if delivery of a software interrupt, software exception or privileged
16206 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
16207 */
16208 VMXVEXITINFO ExitInfo;
16209 RT_ZERO(ExitInfo);
16210 ExitInfo.uReason = pVmxTransient->uExitReason;
16211 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16212 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16213
16214 VMXVEXITEVENTINFO ExitEventInfo;
16215 RT_ZERO(ExitEventInfo);
16216 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
16217 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
16218 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16219 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16220
16221#ifdef DEBUG_ramshankar
16222 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16223 Log4Func(("exit_int_info=%#RX32 err_code=%#RX32 exit_qual=%#RX64\n", pVmxTransient->uExitIntInfo,
16224 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual));
16225 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16226 {
16227 Log4Func(("idt_info=%#RX32 idt_errcode=%#RX32 cr2=%#RX64\n", pVmxTransient->uIdtVectoringInfo,
16228 pVmxTransient->uIdtVectoringErrorCode, pCtx->cr2));
16229 }
16230#endif
16231 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
16232 }
16233
16234 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs in hmR0VmxExitXcptPF. */
16235 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16236 return hmR0VmxExitXcpt(pVCpu, pVmxTransient);
16237 }
16238
16239 /*
16240 * Software interrupts:
16241 * VM-exits cannot be caused by software interrupts.
16242 *
16243 * External interrupts:
16244 * This should only happen when "acknowledge external interrupts on VM-exit"
16245 * control is set. However, we never set this when executing a guest or
16246 * nested-guest. For nested-guests it is emulated while injecting interrupts into
16247 * the guest.
16248 */
16249 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
16250 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
16251 default:
16252 {
16253 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
16254 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
16255 }
16256 }
16257}
16258
16259
16260/**
16261 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
16262 * Unconditional VM-exit.
16263 */
16264HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16265{
16266 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16267 return IEMExecVmxVmexitTripleFault(pVCpu);
16268}
16269
16270
16271/**
16272 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
16273 */
16274HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16275{
16276 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16277
16278 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
16279 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16280 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16281}
16282
16283
16284/**
16285 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
16286 */
16287HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16288{
16289 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16290
16291 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
16292 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
16293 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
16294}
16295
16296
16297/**
16298 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
16299 * Unconditional VM-exit.
16300 */
16301HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16302{
16303 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16304
16305 hmR0VmxReadExitQualVmcs(pVmxTransient);
16306 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16307 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16308 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16309
16310 VMXVEXITINFO ExitInfo;
16311 RT_ZERO(ExitInfo);
16312 ExitInfo.uReason = pVmxTransient->uExitReason;
16313 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16314 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16315
16316 VMXVEXITEVENTINFO ExitEventInfo;
16317 RT_ZERO(ExitEventInfo);
16318 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16319 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16320 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
16321}
16322
16323
16324/**
16325 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
16326 */
16327HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16328{
16329 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16330
16331 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
16332 {
16333 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16334 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16335 }
16336 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
16337}
16338
16339
16340/**
16341 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
16342 */
16343HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16344{
16345 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16346
16347 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16348 {
16349 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16350 hmR0VmxReadExitQualVmcs(pVmxTransient);
16351
16352 VMXVEXITINFO ExitInfo;
16353 RT_ZERO(ExitInfo);
16354 ExitInfo.uReason = pVmxTransient->uExitReason;
16355 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16356 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16357 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16358 }
16359 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
16360}
16361
16362
16363/**
16364 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
16365 */
16366HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16367{
16368 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16369
16370 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
16371 {
16372 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16373 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16374 }
16375 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
16376}
16377
16378
16379/**
16380 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
16381 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
16382 */
16383HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16384{
16385 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16386
16387 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
16388 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
16389
16390 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16391
16392 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
16393 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16394 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16395
16396 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
16397 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
16398 u64VmcsField &= UINT64_C(0xffffffff);
16399
16400 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
16401 {
16402 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16403 hmR0VmxReadExitQualVmcs(pVmxTransient);
16404
16405 VMXVEXITINFO ExitInfo;
16406 RT_ZERO(ExitInfo);
16407 ExitInfo.uReason = pVmxTransient->uExitReason;
16408 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16409 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16410 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16411 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16412 }
16413
16414 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
16415 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
16416 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
16417}
16418
16419
16420/**
16421 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
16422 */
16423HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16424{
16425 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16426
16427 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16428 {
16429 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16430 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16431 }
16432
16433 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
16434}
16435
16436
16437/**
16438 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
16439 * Conditional VM-exit.
16440 */
16441HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16442{
16443 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16444
16445 hmR0VmxReadExitQualVmcs(pVmxTransient);
16446 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16447
16448 VBOXSTRICTRC rcStrict;
16449 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
16450 switch (uAccessType)
16451 {
16452 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
16453 {
16454 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16455 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16456 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
16457 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
16458
16459 bool fIntercept;
16460 switch (iCrReg)
16461 {
16462 case 0:
16463 case 4:
16464 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
16465 break;
16466
16467 case 3:
16468 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
16469 break;
16470
16471 case 8:
16472 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
16473 break;
16474
16475 default:
16476 fIntercept = false;
16477 break;
16478 }
16479 if (fIntercept)
16480 {
16481 VMXVEXITINFO ExitInfo;
16482 RT_ZERO(ExitInfo);
16483 ExitInfo.uReason = pVmxTransient->uExitReason;
16484 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16485 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16486 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16487 }
16488 else
16489 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16490 break;
16491 }
16492
16493 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
16494 {
16495 /*
16496 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
16497 * CR2 reads do not cause a VM-exit.
16498 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
16499 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
16500 */
16501 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
16502 if ( iCrReg == 3
16503 || iCrReg == 8)
16504 {
16505 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
16506 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
16507 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
16508 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
16509 {
16510 VMXVEXITINFO ExitInfo;
16511 RT_ZERO(ExitInfo);
16512 ExitInfo.uReason = pVmxTransient->uExitReason;
16513 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16514 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16515 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16516 }
16517 else
16518 {
16519 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
16520 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, iGReg, iCrReg);
16521 }
16522 }
16523 else
16524 {
16525 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
16526 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
16527 }
16528 break;
16529 }
16530
16531 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
16532 {
16533 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
16534 Assert(pVmcsNstGst);
16535 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
16536 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
16537 if ( (uGstHostMask & X86_CR0_TS)
16538 && (uReadShadow & X86_CR0_TS))
16539 {
16540 VMXVEXITINFO ExitInfo;
16541 RT_ZERO(ExitInfo);
16542 ExitInfo.uReason = pVmxTransient->uExitReason;
16543 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16544 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16545 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16546 }
16547 else
16548 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr);
16549 break;
16550 }
16551
16552 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
16553 {
16554 RTGCPTR GCPtrEffDst;
16555 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
16556 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
16557 if (fMemOperand)
16558 {
16559 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16560 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
16561 }
16562 else
16563 GCPtrEffDst = NIL_RTGCPTR;
16564
16565 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
16566 {
16567 VMXVEXITINFO ExitInfo;
16568 RT_ZERO(ExitInfo);
16569 ExitInfo.uReason = pVmxTransient->uExitReason;
16570 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16571 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
16572 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16573 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16574 }
16575 else
16576 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbExitInstr, uNewMsw, GCPtrEffDst);
16577 break;
16578 }
16579
16580 default:
16581 {
16582 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
16583 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
16584 }
16585 }
16586
16587 if (rcStrict == VINF_IEM_RAISED_XCPT)
16588 {
16589 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16590 rcStrict = VINF_SUCCESS;
16591 }
16592 return rcStrict;
16593}
16594
16595
16596/**
16597 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
16598 * Conditional VM-exit.
16599 */
16600HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16601{
16602 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16603
16604 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
16605 {
16606 hmR0VmxReadExitQualVmcs(pVmxTransient);
16607 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16608
16609 VMXVEXITINFO ExitInfo;
16610 RT_ZERO(ExitInfo);
16611 ExitInfo.uReason = pVmxTransient->uExitReason;
16612 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16613 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16614 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16615 }
16616 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
16617}
16618
16619
16620/**
16621 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
16622 * Conditional VM-exit.
16623 */
16624HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16625{
16626 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16627
16628 hmR0VmxReadExitQualVmcs(pVmxTransient);
16629
16630 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16631 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16632 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16633
16634 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16635 uint8_t const cbAccess = s_aIOSizes[uIOSize];
16636 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
16637 {
16638 /*
16639 * IN/OUT instruction:
16640 * - Provides VM-exit instruction length.
16641 *
16642 * INS/OUTS instruction:
16643 * - Provides VM-exit instruction length.
16644 * - Provides Guest-linear address.
16645 * - Optionally provides VM-exit instruction info (depends on CPU feature).
16646 */
16647 PVMCC pVM = pVCpu->CTX_SUFF(pVM);
16648 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16649
16650 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
16651 pVmxTransient->ExitInstrInfo.u = 0;
16652 pVmxTransient->uGuestLinearAddr = 0;
16653
16654 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
16655 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16656 if (fIOString)
16657 {
16658 hmR0VmxReadGuestLinearAddrVmcs(pVmxTransient);
16659 if (fVmxInsOutsInfo)
16660 {
16661 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
16662 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16663 }
16664 }
16665
16666 VMXVEXITINFO ExitInfo;
16667 RT_ZERO(ExitInfo);
16668 ExitInfo.uReason = pVmxTransient->uExitReason;
16669 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16670 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16671 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16672 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
16673 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16674 }
16675 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
16676}
16677
16678
16679/**
16680 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
16681 */
16682HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16683{
16684 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16685
16686 uint32_t fMsrpm;
16687 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16688 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16689 else
16690 fMsrpm = VMXMSRPM_EXIT_RD;
16691
16692 if (fMsrpm & VMXMSRPM_EXIT_RD)
16693 {
16694 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16695 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16696 }
16697 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
16698}
16699
16700
16701/**
16702 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
16703 */
16704HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16705{
16706 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16707
16708 uint32_t fMsrpm;
16709 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
16710 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
16711 else
16712 fMsrpm = VMXMSRPM_EXIT_WR;
16713
16714 if (fMsrpm & VMXMSRPM_EXIT_WR)
16715 {
16716 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16717 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16718 }
16719 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
16720}
16721
16722
16723/**
16724 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
16725 */
16726HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16727{
16728 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16729
16730 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
16731 {
16732 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16733 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16734 }
16735 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
16736}
16737
16738
16739/**
16740 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
16741 * VM-exit.
16742 */
16743HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16744{
16745 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16746
16747 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
16748 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16749 VMXVEXITINFO ExitInfo;
16750 RT_ZERO(ExitInfo);
16751 ExitInfo.uReason = pVmxTransient->uExitReason;
16752 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16753 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16754}
16755
16756
16757/**
16758 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
16759 */
16760HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16761{
16762 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16763
16764 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
16765 {
16766 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16767 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16768 }
16769 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
16770}
16771
16772
16773/**
16774 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
16775 */
16776HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16777{
16778 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16779
16780 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
16781 * PAUSE when executing a nested-guest? If it does not, we would not need
16782 * to check for the intercepts here. Just call VM-exit... */
16783
16784 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
16785 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
16786 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
16787 {
16788 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16789 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16790 }
16791 return hmR0VmxExitPause(pVCpu, pVmxTransient);
16792}
16793
16794
16795/**
16796 * Nested-guest VM-exit handler for when the TPR value is lowered below the
16797 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
16798 */
16799HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16800{
16801 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16802
16803 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
16804 {
16805 hmR0VmxReadGuestPendingDbgXctps(pVmxTransient);
16806 VMXVEXITINFO ExitInfo;
16807 RT_ZERO(ExitInfo);
16808 ExitInfo.uReason = pVmxTransient->uExitReason;
16809 ExitInfo.u64GuestPendingDbgXcpts = pVmxTransient->uGuestPendingDbgXcpts;
16810 return IEMExecVmxVmexitTrapLike(pVCpu, &ExitInfo);
16811 }
16812 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
16813}
16814
16815
16816/**
16817 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
16818 * VM-exit.
16819 */
16820HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16821{
16822 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16823
16824 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16825 hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16826 hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16827 hmR0VmxReadExitQualVmcs(pVmxTransient);
16828
16829 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
16830
16831 Log4Func(("at offset %#x type=%u\n", VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual),
16832 VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual)));
16833
16834 VMXVEXITINFO ExitInfo;
16835 RT_ZERO(ExitInfo);
16836 ExitInfo.uReason = pVmxTransient->uExitReason;
16837 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16838 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16839
16840 VMXVEXITEVENTINFO ExitEventInfo;
16841 RT_ZERO(ExitEventInfo);
16842 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
16843 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
16844 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
16845}
16846
16847
16848/**
16849 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
16850 * Conditional VM-exit.
16851 */
16852HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16853{
16854 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16855
16856 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
16857 hmR0VmxReadExitQualVmcs(pVmxTransient);
16858 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16859}
16860
16861
16862/**
16863 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
16864 * Conditional VM-exit.
16865 */
16866HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16867{
16868 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16869
16870 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
16871 hmR0VmxReadExitQualVmcs(pVmxTransient);
16872 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
16873}
16874
16875
16876/**
16877 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
16878 */
16879HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16880{
16881 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16882
16883 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
16884 {
16885 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
16886 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16887 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16888 }
16889 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
16890}
16891
16892
16893/**
16894 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
16895 */
16896HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16897{
16898 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16899
16900 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
16901 {
16902 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16903 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16904 }
16905 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
16906}
16907
16908
16909/**
16910 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
16911 */
16912HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16913{
16914 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16915
16916 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
16917 {
16918 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
16919 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16920 hmR0VmxReadExitQualVmcs(pVmxTransient);
16921 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16922
16923 VMXVEXITINFO ExitInfo;
16924 RT_ZERO(ExitInfo);
16925 ExitInfo.uReason = pVmxTransient->uExitReason;
16926 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
16927 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16928 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
16929 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
16930 }
16931 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
16932}
16933
16934
16935/**
16936 * Nested-guest VM-exit handler for invalid-guest state
16937 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
16938 */
16939HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16940{
16941 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16942
16943 /*
16944 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
16945 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
16946 * Handle it like it's in an invalid guest state of the outer guest.
16947 *
16948 * When the fast path is implemented, this should be changed to cause the corresponding
16949 * nested-guest VM-exit.
16950 */
16951 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
16952}
16953
16954
16955/**
16956 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
16957 * and only provide the instruction length.
16958 *
16959 * Unconditional VM-exit.
16960 */
16961HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16962{
16963 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16964
16965#ifdef VBOX_STRICT
16966 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16967 switch (pVmxTransient->uExitReason)
16968 {
16969 case VMX_EXIT_ENCLS:
16970 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
16971 break;
16972
16973 case VMX_EXIT_VMFUNC:
16974 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
16975 break;
16976 }
16977#endif
16978
16979 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16980 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbExitInstr);
16981}
16982
16983
16984/**
16985 * Nested-guest VM-exit handler for instructions that provide instruction length as
16986 * well as more information.
16987 *
16988 * Unconditional VM-exit.
16989 */
16990HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPUCC pVCpu, PVMXTRANSIENT pVmxTransient)
16991{
16992 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16993
16994#ifdef VBOX_STRICT
16995 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16996 switch (pVmxTransient->uExitReason)
16997 {
16998 case VMX_EXIT_GDTR_IDTR_ACCESS:
16999 case VMX_EXIT_LDTR_TR_ACCESS:
17000 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17001 break;
17002
17003 case VMX_EXIT_RDRAND:
17004 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17005 break;
17006
17007 case VMX_EXIT_RDSEED:
17008 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17009 break;
17010
17011 case VMX_EXIT_XSAVES:
17012 case VMX_EXIT_XRSTORS:
17013 /** @todo NSTVMX: Verify XSS-bitmap. */
17014 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17015 break;
17016
17017 case VMX_EXIT_UMWAIT:
17018 case VMX_EXIT_TPAUSE:
17019 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17020 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17021 break;
17022 }
17023#endif
17024
17025 hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17026 hmR0VmxReadExitQualVmcs(pVmxTransient);
17027 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17028
17029 VMXVEXITINFO ExitInfo;
17030 RT_ZERO(ExitInfo);
17031 ExitInfo.uReason = pVmxTransient->uExitReason;
17032 ExitInfo.cbInstr = pVmxTransient->cbExitInstr;
17033 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17034 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17035 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17036}
17037
17038/** @} */
17039#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17040
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