VirtualBox

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

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

VMM/HMVMXR0: Nested VMX: bugref:9180 Comment.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 740.8 KB
Line 
1/* $Id: HMVMXR0.cpp 79753 2019-07-13 11:34:54Z vboxsync $ */
2/** @file
3 * HM VMX (Intel VT-x) - Host Context Ring-0.
4 */
5
6/*
7 * Copyright (C) 2012-2019 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18
19/*********************************************************************************************************************************
20* Header Files *
21*********************************************************************************************************************************/
22#define LOG_GROUP LOG_GROUP_HM
23#define VMCPU_INCL_CPUM_GST_CTX
24#include <iprt/x86.h>
25#include <iprt/asm-amd64-x86.h>
26#include <iprt/thread.h>
27#include <iprt/mem.h>
28#include <iprt/mp.h>
29
30#include <VBox/vmm/pdmapi.h>
31#include <VBox/vmm/dbgf.h>
32#include <VBox/vmm/iem.h>
33#include <VBox/vmm/iom.h>
34#include <VBox/vmm/selm.h>
35#include <VBox/vmm/tm.h>
36#include <VBox/vmm/em.h>
37#include <VBox/vmm/gim.h>
38#include <VBox/vmm/apic.h>
39#ifdef VBOX_WITH_REM
40# include <VBox/vmm/rem.h>
41#endif
42#include "HMInternal.h"
43#include <VBox/vmm/vm.h>
44#include <VBox/vmm/hmvmxinline.h>
45#include "HMVMXR0.h"
46#include "dtrace/VBoxVMM.h"
47
48#ifdef DEBUG_ramshankar
49# define HMVMX_ALWAYS_SAVE_GUEST_RFLAGS
50# define HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE
51# define HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
52# define HMVMX_ALWAYS_CLEAN_TRANSIENT
53# define HMVMX_ALWAYS_CHECK_GUEST_STATE
54# define HMVMX_ALWAYS_TRAP_ALL_XCPTS
55# define HMVMX_ALWAYS_TRAP_PF
56# define HMVMX_ALWAYS_FLUSH_TLB
57# define HMVMX_ALWAYS_SWAP_EFER
58#endif
59
60
61/*********************************************************************************************************************************
62* Defined Constants And Macros *
63*********************************************************************************************************************************/
64/** Use the function table. */
65#define HMVMX_USE_FUNCTION_TABLE
66
67/** Determine which tagged-TLB flush handler to use. */
68#define HMVMX_FLUSH_TAGGED_TLB_EPT_VPID 0
69#define HMVMX_FLUSH_TAGGED_TLB_EPT 1
70#define HMVMX_FLUSH_TAGGED_TLB_VPID 2
71#define HMVMX_FLUSH_TAGGED_TLB_NONE 3
72
73/** @name HMVMX_READ_XXX
74 * Flags to skip redundant reads of some common VMCS fields that are not part of
75 * the guest-CPU or VCPU state but are needed while handling VM-exits.
76 */
77#define HMVMX_READ_IDT_VECTORING_INFO RT_BIT_32(0)
78#define HMVMX_READ_IDT_VECTORING_ERROR_CODE RT_BIT_32(1)
79#define HMVMX_READ_EXIT_QUALIFICATION RT_BIT_32(2)
80#define HMVMX_READ_EXIT_INSTR_LEN RT_BIT_32(3)
81#define HMVMX_READ_EXIT_INTERRUPTION_INFO RT_BIT_32(4)
82#define HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE RT_BIT_32(5)
83#define HMVMX_READ_EXIT_INSTR_INFO RT_BIT_32(6)
84#define HMVMX_READ_GUEST_LINEAR_ADDR RT_BIT_32(7)
85/** @} */
86
87/** All the VMCS fields required for our processing of exception/NMI VM-exits. */
88#define HMVMX_READ_XCPT_INFO ( HMVMX_READ_EXIT_INTERRUPTION_INFO \
89 | HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE \
90 | HMVMX_READ_EXIT_INSTR_LEN \
91 | HMVMX_READ_IDT_VECTORING_INFO \
92 | HMVMX_READ_IDT_VECTORING_ERROR_CODE)
93
94/**
95 * Subset of the guest-CPU state that is kept by VMX R0 code while executing the
96 * guest using hardware-assisted VMX.
97 *
98 * This excludes state like GPRs (other than RSP) which are always are
99 * swapped and restored across the world-switch and also registers like EFER,
100 * MSR which cannot be modified by the guest without causing a VM-exit.
101 */
102#define HMVMX_CPUMCTX_EXTRN_ALL ( CPUMCTX_EXTRN_RIP \
103 | CPUMCTX_EXTRN_RFLAGS \
104 | CPUMCTX_EXTRN_RSP \
105 | CPUMCTX_EXTRN_SREG_MASK \
106 | CPUMCTX_EXTRN_TABLE_MASK \
107 | CPUMCTX_EXTRN_KERNEL_GS_BASE \
108 | CPUMCTX_EXTRN_SYSCALL_MSRS \
109 | CPUMCTX_EXTRN_SYSENTER_MSRS \
110 | CPUMCTX_EXTRN_TSC_AUX \
111 | CPUMCTX_EXTRN_OTHER_MSRS \
112 | CPUMCTX_EXTRN_CR0 \
113 | CPUMCTX_EXTRN_CR3 \
114 | CPUMCTX_EXTRN_CR4 \
115 | CPUMCTX_EXTRN_DR7 \
116 | CPUMCTX_EXTRN_HWVIRT \
117 | CPUMCTX_EXTRN_HM_VMX_MASK)
118
119/**
120 * Exception bitmap mask for real-mode guests (real-on-v86).
121 *
122 * We need to intercept all exceptions manually except:
123 * - \#AC and \#DB are always intercepted to prevent the CPU from deadlocking
124 * due to bugs in Intel CPUs.
125 * - \#PF need not be intercepted even in real-mode if we have nested paging
126 * support.
127 */
128#define HMVMX_REAL_MODE_XCPT_MASK ( RT_BIT(X86_XCPT_DE) /* always: | RT_BIT(X86_XCPT_DB) */ | RT_BIT(X86_XCPT_NMI) \
129 | RT_BIT(X86_XCPT_BP) | RT_BIT(X86_XCPT_OF) | RT_BIT(X86_XCPT_BR) \
130 | RT_BIT(X86_XCPT_UD) | RT_BIT(X86_XCPT_NM) | RT_BIT(X86_XCPT_DF) \
131 | RT_BIT(X86_XCPT_CO_SEG_OVERRUN) | RT_BIT(X86_XCPT_TS) | RT_BIT(X86_XCPT_NP) \
132 | RT_BIT(X86_XCPT_SS) | RT_BIT(X86_XCPT_GP) /* RT_BIT(X86_XCPT_PF) */ \
133 | RT_BIT(X86_XCPT_MF) /* always: | RT_BIT(X86_XCPT_AC) */ | RT_BIT(X86_XCPT_MC) \
134 | RT_BIT(X86_XCPT_XF))
135
136/** Maximum VM-instruction error number. */
137#define HMVMX_INSTR_ERROR_MAX 28
138
139/** Profiling macro. */
140#ifdef HM_PROFILE_EXIT_DISPATCH
141# define HMVMX_START_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitDispatch, ed)
142# define HMVMX_STOP_EXIT_DISPATCH_PROF() STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitDispatch, ed)
143#else
144# define HMVMX_START_EXIT_DISPATCH_PROF() do { } while (0)
145# define HMVMX_STOP_EXIT_DISPATCH_PROF() do { } while (0)
146#endif
147
148/** Assert that preemption is disabled or covered by thread-context hooks. */
149#define HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu) Assert( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
150 || !RTThreadPreemptIsEnabled(NIL_RTTHREAD))
151
152/** Assert that we haven't migrated CPUs when thread-context hooks are not
153 * used. */
154#define HMVMX_ASSERT_CPU_SAFE(a_pVCpu) AssertMsg( VMMR0ThreadCtxHookIsEnabled((a_pVCpu)) \
155 || (a_pVCpu)->hm.s.idEnteredCpu == RTMpCpuId(), \
156 ("Illegal migration! Entered on CPU %u Current %u\n", \
157 (a_pVCpu)->hm.s.idEnteredCpu, RTMpCpuId()))
158
159/** Asserts that the given CPUMCTX_EXTRN_XXX bits are present in the guest-CPU
160 * context. */
161#define HMVMX_CPUMCTX_ASSERT(a_pVCpu, a_fExtrnMbz) AssertMsg(!((a_pVCpu)->cpum.GstCtx.fExtrn & (a_fExtrnMbz)), \
162 ("fExtrn=%#RX64 fExtrnMbz=%#RX64\n", \
163 (a_pVCpu)->cpum.GstCtx.fExtrn, (a_fExtrnMbz)))
164
165/** Log the VM-exit reason with an easily visible marker to identify it in a
166 * potential sea of logging data. */
167#define HMVMX_LOG_EXIT(a_pVCpu, a_uExitReason) \
168 do { \
169 Log4(("VM-exit: vcpu[%RU32] reason=%#x -v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v-v\n", \
170 (a_pVCpu)->idCpu, (a_uExitReason))); \
171 } while (0) \
172
173
174/*********************************************************************************************************************************
175* Structures and Typedefs *
176*********************************************************************************************************************************/
177/**
178 * VMX per-VCPU transient state.
179 *
180 * A state structure for holding miscellaneous information across
181 * VMX non-root operation and restored after the transition.
182 */
183typedef struct VMXTRANSIENT
184{
185 /** The host's rflags/eflags. */
186 RTCCUINTREG fEFlags;
187#if HC_ARCH_BITS == 32
188 uint32_t u32Alignment0;
189#endif
190 /** The guest's TPR value used for TPR shadowing. */
191 uint8_t u8GuestTpr;
192 /** Alignment. */
193 uint8_t abAlignment0[7];
194
195 /** The basic VM-exit reason. */
196 uint16_t uExitReason;
197 /** Alignment. */
198 uint16_t u16Alignment0;
199 /** The VM-exit interruption error code. */
200 uint32_t uExitIntErrorCode;
201 /** The VM-exit exit code qualification. */
202 uint64_t uExitQual;
203 /** The Guest-linear address. */
204 uint64_t uGuestLinearAddr;
205
206 /** The VM-exit interruption-information field. */
207 uint32_t uExitIntInfo;
208 /** The VM-exit instruction-length field. */
209 uint32_t cbInstr;
210 /** The VM-exit instruction-information field. */
211 VMXEXITINSTRINFO ExitInstrInfo;
212 /** Whether the VM-entry failed or not. */
213 bool fVMEntryFailed;
214 /** Whether we are currently executing a nested-guest. */
215 bool fIsNestedGuest;
216 /** Alignment. */
217 uint8_t abAlignment1[2];
218
219 /** The VM-entry interruption-information field. */
220 uint32_t uEntryIntInfo;
221 /** The VM-entry exception error code field. */
222 uint32_t uEntryXcptErrorCode;
223 /** The VM-entry instruction length field. */
224 uint32_t cbEntryInstr;
225
226 /** IDT-vectoring information field. */
227 uint32_t uIdtVectoringInfo;
228 /** IDT-vectoring error code. */
229 uint32_t uIdtVectoringErrorCode;
230
231 /** Mask of currently read VMCS fields; HMVMX_READ_XXX. */
232 uint32_t fVmcsFieldsRead;
233
234 /** Whether the guest debug state was active at the time of VM-exit. */
235 bool fWasGuestDebugStateActive;
236 /** Whether the hyper debug state was active at the time of VM-exit. */
237 bool fWasHyperDebugStateActive;
238 /** Whether TSC-offsetting and VMX-preemption timer was updated before VM-entry. */
239 bool fUpdatedTscOffsettingAndPreemptTimer;
240 /** Whether the VM-exit was caused by a page-fault during delivery of a
241 * contributory exception or a page-fault. */
242 bool fVectoringDoublePF;
243 /** Whether the VM-exit was caused by a page-fault during delivery of an
244 * external interrupt or NMI. */
245 bool fVectoringPF;
246 /** Whether the TSC_AUX MSR needs to be removed from the auto-load/store MSR
247 * area after VM-exit. */
248 bool fRemoveTscAuxMsr;
249 bool afAlignment0[2];
250
251 /** The VMCS info. object. */
252 PVMXVMCSINFO pVmcsInfo;
253} VMXTRANSIENT;
254AssertCompileMemberAlignment(VMXTRANSIENT, uExitReason, sizeof(uint64_t));
255AssertCompileMemberAlignment(VMXTRANSIENT, uExitIntInfo, sizeof(uint64_t));
256AssertCompileMemberAlignment(VMXTRANSIENT, uEntryIntInfo, sizeof(uint64_t));
257AssertCompileMemberAlignment(VMXTRANSIENT, fWasGuestDebugStateActive, sizeof(uint64_t));
258AssertCompileMemberAlignment(VMXTRANSIENT, pVmcsInfo, sizeof(uint64_t));
259AssertCompileMemberSize(VMXTRANSIENT, ExitInstrInfo, sizeof(uint32_t));
260/** Pointer to VMX transient state. */
261typedef VMXTRANSIENT *PVMXTRANSIENT;
262/** Pointer to a const VMX transient state. */
263typedef const VMXTRANSIENT *PCVMXTRANSIENT;
264
265/**
266 * Memory operand read or write access.
267 */
268typedef enum VMXMEMACCESS
269{
270 VMXMEMACCESS_READ = 0,
271 VMXMEMACCESS_WRITE = 1
272} VMXMEMACCESS;
273
274/**
275 * VMX VM-exit handler.
276 *
277 * @returns Strict VBox status code (i.e. informational status codes too).
278 * @param pVCpu The cross context virtual CPU structure.
279 * @param pVmxTransient The VMX-transient structure.
280 */
281#ifndef HMVMX_USE_FUNCTION_TABLE
282typedef VBOXSTRICTRC FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
283#else
284typedef DECLCALLBACK(VBOXSTRICTRC) FNVMXEXITHANDLER(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
285/** Pointer to VM-exit handler. */
286typedef FNVMXEXITHANDLER *PFNVMXEXITHANDLER;
287#endif
288
289/**
290 * VMX VM-exit handler, non-strict status code.
291 *
292 * This is generally the same as FNVMXEXITHANDLER, the NSRC bit is just FYI.
293 *
294 * @returns VBox status code, no informational status code returned.
295 * @param pVCpu The cross context virtual CPU structure.
296 * @param pVmxTransient The VMX-transient structure.
297 *
298 * @remarks This is not used on anything returning VERR_EM_INTERPRETER as the
299 * use of that status code will be replaced with VINF_EM_SOMETHING
300 * later when switching over to IEM.
301 */
302#ifndef HMVMX_USE_FUNCTION_TABLE
303typedef int FNVMXEXITHANDLERNSRC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
304#else
305typedef FNVMXEXITHANDLER FNVMXEXITHANDLERNSRC;
306#endif
307
308
309/*********************************************************************************************************************************
310* Internal Functions *
311*********************************************************************************************************************************/
312#ifndef HMVMX_USE_FUNCTION_TABLE
313DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
314# define HMVMX_EXIT_DECL DECLINLINE(VBOXSTRICTRC)
315# define HMVMX_EXIT_NSRC_DECL DECLINLINE(int)
316#else
317# define HMVMX_EXIT_DECL static DECLCALLBACK(VBOXSTRICTRC)
318# define HMVMX_EXIT_NSRC_DECL HMVMX_EXIT_DECL
319#endif
320#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
321DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient);
322#endif
323
324static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat);
325#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
326static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu);
327#endif
328
329/** @name VM-exit handler prototypes.
330 * @{
331 */
332static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmi;
333static FNVMXEXITHANDLER hmR0VmxExitExtInt;
334static FNVMXEXITHANDLER hmR0VmxExitTripleFault;
335static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindow;
336static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindow;
337static FNVMXEXITHANDLER hmR0VmxExitTaskSwitch;
338static FNVMXEXITHANDLER hmR0VmxExitCpuid;
339static FNVMXEXITHANDLER hmR0VmxExitGetsec;
340static FNVMXEXITHANDLER hmR0VmxExitHlt;
341static FNVMXEXITHANDLERNSRC hmR0VmxExitInvd;
342static FNVMXEXITHANDLER hmR0VmxExitInvlpg;
343static FNVMXEXITHANDLER hmR0VmxExitRdpmc;
344static FNVMXEXITHANDLER hmR0VmxExitVmcall;
345#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
346static FNVMXEXITHANDLER hmR0VmxExitVmclear;
347static FNVMXEXITHANDLER hmR0VmxExitVmlaunch;
348static FNVMXEXITHANDLER hmR0VmxExitVmptrld;
349static FNVMXEXITHANDLER hmR0VmxExitVmptrst;
350static FNVMXEXITHANDLER hmR0VmxExitVmread;
351static FNVMXEXITHANDLER hmR0VmxExitVmresume;
352static FNVMXEXITHANDLER hmR0VmxExitVmwrite;
353static FNVMXEXITHANDLER hmR0VmxExitVmxoff;
354static FNVMXEXITHANDLER hmR0VmxExitVmxon;
355static FNVMXEXITHANDLER hmR0VmxExitInvvpid;
356#endif
357static FNVMXEXITHANDLER hmR0VmxExitRdtsc;
358static FNVMXEXITHANDLER hmR0VmxExitMovCRx;
359static FNVMXEXITHANDLER hmR0VmxExitMovDRx;
360static FNVMXEXITHANDLER hmR0VmxExitIoInstr;
361static FNVMXEXITHANDLER hmR0VmxExitRdmsr;
362static FNVMXEXITHANDLER hmR0VmxExitWrmsr;
363static FNVMXEXITHANDLER hmR0VmxExitMwait;
364static FNVMXEXITHANDLER hmR0VmxExitMtf;
365static FNVMXEXITHANDLER hmR0VmxExitMonitor;
366static FNVMXEXITHANDLER hmR0VmxExitPause;
367static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThreshold;
368static FNVMXEXITHANDLER hmR0VmxExitApicAccess;
369static FNVMXEXITHANDLER hmR0VmxExitEptViolation;
370static FNVMXEXITHANDLER hmR0VmxExitEptMisconfig;
371static FNVMXEXITHANDLER hmR0VmxExitRdtscp;
372static FNVMXEXITHANDLER hmR0VmxExitPreemptTimer;
373static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvd;
374static FNVMXEXITHANDLER hmR0VmxExitXsetbv;
375static FNVMXEXITHANDLER hmR0VmxExitInvpcid;
376static FNVMXEXITHANDLERNSRC hmR0VmxExitSetPendingXcptUD;
377static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestState;
378static FNVMXEXITHANDLERNSRC hmR0VmxExitErrUnexpected;
379/** @} */
380
381#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
382/** @name Nested-guest VM-exit handler prototypes.
383 * @{
384 */
385static FNVMXEXITHANDLER hmR0VmxExitXcptOrNmiNested;
386static FNVMXEXITHANDLER hmR0VmxExitTripleFaultNested;
387static FNVMXEXITHANDLERNSRC hmR0VmxExitIntWindowNested;
388static FNVMXEXITHANDLERNSRC hmR0VmxExitNmiWindowNested;
389static FNVMXEXITHANDLER hmR0VmxExitTaskSwitchNested;
390static FNVMXEXITHANDLER hmR0VmxExitHltNested;
391static FNVMXEXITHANDLER hmR0VmxExitInvlpgNested;
392static FNVMXEXITHANDLER hmR0VmxExitRdpmcNested;
393static FNVMXEXITHANDLER hmR0VmxExitVmreadVmwriteNested;
394static FNVMXEXITHANDLER hmR0VmxExitRdtscNested;
395static FNVMXEXITHANDLER hmR0VmxExitMovCRxNested;
396static FNVMXEXITHANDLER hmR0VmxExitMovDRxNested;
397static FNVMXEXITHANDLER hmR0VmxExitIoInstrNested;
398static FNVMXEXITHANDLER hmR0VmxExitRdmsrNested;
399static FNVMXEXITHANDLER hmR0VmxExitWrmsrNested;
400static FNVMXEXITHANDLER hmR0VmxExitMwaitNested;
401static FNVMXEXITHANDLER hmR0VmxExitMtfNested;
402static FNVMXEXITHANDLER hmR0VmxExitMonitorNested;
403static FNVMXEXITHANDLER hmR0VmxExitPauseNested;
404static FNVMXEXITHANDLERNSRC hmR0VmxExitTprBelowThresholdNested;
405static FNVMXEXITHANDLER hmR0VmxExitApicAccessNested;
406static FNVMXEXITHANDLER hmR0VmxExitApicWriteNested;
407static FNVMXEXITHANDLER hmR0VmxExitVirtEoiNested;
408static FNVMXEXITHANDLER hmR0VmxExitRdtscpNested;
409static FNVMXEXITHANDLERNSRC hmR0VmxExitWbinvdNested;
410static FNVMXEXITHANDLER hmR0VmxExitInvpcidNested;
411static FNVMXEXITHANDLERNSRC hmR0VmxExitErrInvalidGuestStateNested;
412static FNVMXEXITHANDLER hmR0VmxExitInstrNested;
413static FNVMXEXITHANDLER hmR0VmxExitInstrWithInfoNested;
414/** @} */
415#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
416
417
418/*********************************************************************************************************************************
419* Global Variables *
420*********************************************************************************************************************************/
421#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
422/**
423 * Array of all VMCS fields.
424 * Any fields added to the VT-x spec. should be added here.
425 *
426 * Currently only used to derive shadow VMCS fields for hardware-assisted execution
427 * of nested-guests.
428 */
429static const uint32_t g_aVmcsFields[] =
430{
431 /* 16-bit control fields. */
432 VMX_VMCS16_VPID,
433 VMX_VMCS16_POSTED_INT_NOTIFY_VECTOR,
434 VMX_VMCS16_EPTP_INDEX,
435
436 /* 16-bit guest-state fields. */
437 VMX_VMCS16_GUEST_ES_SEL,
438 VMX_VMCS16_GUEST_CS_SEL,
439 VMX_VMCS16_GUEST_SS_SEL,
440 VMX_VMCS16_GUEST_DS_SEL,
441 VMX_VMCS16_GUEST_FS_SEL,
442 VMX_VMCS16_GUEST_GS_SEL,
443 VMX_VMCS16_GUEST_LDTR_SEL,
444 VMX_VMCS16_GUEST_TR_SEL,
445 VMX_VMCS16_GUEST_INTR_STATUS,
446 VMX_VMCS16_GUEST_PML_INDEX,
447
448 /* 16-bits host-state fields. */
449 VMX_VMCS16_HOST_ES_SEL,
450 VMX_VMCS16_HOST_CS_SEL,
451 VMX_VMCS16_HOST_SS_SEL,
452 VMX_VMCS16_HOST_DS_SEL,
453 VMX_VMCS16_HOST_FS_SEL,
454 VMX_VMCS16_HOST_GS_SEL,
455 VMX_VMCS16_HOST_TR_SEL,
456
457 /* 64-bit control fields. */
458 VMX_VMCS64_CTRL_IO_BITMAP_A_FULL,
459 VMX_VMCS64_CTRL_IO_BITMAP_A_HIGH,
460 VMX_VMCS64_CTRL_IO_BITMAP_B_FULL,
461 VMX_VMCS64_CTRL_IO_BITMAP_B_HIGH,
462 VMX_VMCS64_CTRL_MSR_BITMAP_FULL,
463 VMX_VMCS64_CTRL_MSR_BITMAP_HIGH,
464 VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL,
465 VMX_VMCS64_CTRL_EXIT_MSR_STORE_HIGH,
466 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL,
467 VMX_VMCS64_CTRL_EXIT_MSR_LOAD_HIGH,
468 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL,
469 VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_HIGH,
470 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL,
471 VMX_VMCS64_CTRL_EXEC_VMCS_PTR_HIGH,
472 VMX_VMCS64_CTRL_EXEC_PML_ADDR_FULL,
473 VMX_VMCS64_CTRL_EXEC_PML_ADDR_HIGH,
474 VMX_VMCS64_CTRL_TSC_OFFSET_FULL,
475 VMX_VMCS64_CTRL_TSC_OFFSET_HIGH,
476 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL,
477 VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_HIGH,
478 VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL,
479 VMX_VMCS64_CTRL_APIC_ACCESSADDR_HIGH,
480 VMX_VMCS64_CTRL_POSTED_INTR_DESC_FULL,
481 VMX_VMCS64_CTRL_POSTED_INTR_DESC_HIGH,
482 VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL,
483 VMX_VMCS64_CTRL_VMFUNC_CTRLS_HIGH,
484 VMX_VMCS64_CTRL_EPTP_FULL,
485 VMX_VMCS64_CTRL_EPTP_HIGH,
486 VMX_VMCS64_CTRL_EOI_BITMAP_0_FULL,
487 VMX_VMCS64_CTRL_EOI_BITMAP_0_HIGH,
488 VMX_VMCS64_CTRL_EOI_BITMAP_1_FULL,
489 VMX_VMCS64_CTRL_EOI_BITMAP_1_HIGH,
490 VMX_VMCS64_CTRL_EOI_BITMAP_2_FULL,
491 VMX_VMCS64_CTRL_EOI_BITMAP_2_HIGH,
492 VMX_VMCS64_CTRL_EOI_BITMAP_3_FULL,
493 VMX_VMCS64_CTRL_EOI_BITMAP_3_HIGH,
494 VMX_VMCS64_CTRL_EPTP_LIST_FULL,
495 VMX_VMCS64_CTRL_EPTP_LIST_HIGH,
496 VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL,
497 VMX_VMCS64_CTRL_VMREAD_BITMAP_HIGH,
498 VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL,
499 VMX_VMCS64_CTRL_VMWRITE_BITMAP_HIGH,
500 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_FULL,
501 VMX_VMCS64_CTRL_VIRTXCPT_INFO_ADDR_HIGH,
502 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_FULL,
503 VMX_VMCS64_CTRL_XSS_EXITING_BITMAP_HIGH,
504 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_FULL,
505 VMX_VMCS64_CTRL_ENCLS_EXITING_BITMAP_HIGH,
506 VMX_VMCS64_CTRL_TSC_MULTIPLIER_FULL,
507 VMX_VMCS64_CTRL_TSC_MULTIPLIER_HIGH,
508
509 /* 64-bit read-only data fields. */
510 VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL,
511 VMX_VMCS64_RO_GUEST_PHYS_ADDR_HIGH,
512
513 /* 64-bit guest-state fields. */
514 VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL,
515 VMX_VMCS64_GUEST_VMCS_LINK_PTR_HIGH,
516 VMX_VMCS64_GUEST_DEBUGCTL_FULL,
517 VMX_VMCS64_GUEST_DEBUGCTL_HIGH,
518 VMX_VMCS64_GUEST_PAT_FULL,
519 VMX_VMCS64_GUEST_PAT_HIGH,
520 VMX_VMCS64_GUEST_EFER_FULL,
521 VMX_VMCS64_GUEST_EFER_HIGH,
522 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL,
523 VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_HIGH,
524 VMX_VMCS64_GUEST_PDPTE0_FULL,
525 VMX_VMCS64_GUEST_PDPTE0_HIGH,
526 VMX_VMCS64_GUEST_PDPTE1_FULL,
527 VMX_VMCS64_GUEST_PDPTE1_HIGH,
528 VMX_VMCS64_GUEST_PDPTE2_FULL,
529 VMX_VMCS64_GUEST_PDPTE2_HIGH,
530 VMX_VMCS64_GUEST_PDPTE3_FULL,
531 VMX_VMCS64_GUEST_PDPTE3_HIGH,
532 VMX_VMCS64_GUEST_BNDCFGS_FULL,
533 VMX_VMCS64_GUEST_BNDCFGS_HIGH,
534
535 /* 64-bit host-state fields. */
536 VMX_VMCS64_HOST_PAT_FULL,
537 VMX_VMCS64_HOST_PAT_HIGH,
538 VMX_VMCS64_HOST_EFER_FULL,
539 VMX_VMCS64_HOST_EFER_HIGH,
540 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL,
541 VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_HIGH,
542
543 /* 32-bit control fields. */
544 VMX_VMCS32_CTRL_PIN_EXEC,
545 VMX_VMCS32_CTRL_PROC_EXEC,
546 VMX_VMCS32_CTRL_EXCEPTION_BITMAP,
547 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK,
548 VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH,
549 VMX_VMCS32_CTRL_CR3_TARGET_COUNT,
550 VMX_VMCS32_CTRL_EXIT,
551 VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT,
552 VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT,
553 VMX_VMCS32_CTRL_ENTRY,
554 VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT,
555 VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO,
556 VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE,
557 VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH,
558 VMX_VMCS32_CTRL_TPR_THRESHOLD,
559 VMX_VMCS32_CTRL_PROC_EXEC2,
560 VMX_VMCS32_CTRL_PLE_GAP,
561 VMX_VMCS32_CTRL_PLE_WINDOW,
562
563 /* 32-bits read-only fields. */
564 VMX_VMCS32_RO_VM_INSTR_ERROR,
565 VMX_VMCS32_RO_EXIT_REASON,
566 VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO,
567 VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE,
568 VMX_VMCS32_RO_IDT_VECTORING_INFO,
569 VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE,
570 VMX_VMCS32_RO_EXIT_INSTR_LENGTH,
571 VMX_VMCS32_RO_EXIT_INSTR_INFO,
572
573 /* 32-bit guest-state fields. */
574 VMX_VMCS32_GUEST_ES_LIMIT,
575 VMX_VMCS32_GUEST_CS_LIMIT,
576 VMX_VMCS32_GUEST_SS_LIMIT,
577 VMX_VMCS32_GUEST_DS_LIMIT,
578 VMX_VMCS32_GUEST_FS_LIMIT,
579 VMX_VMCS32_GUEST_GS_LIMIT,
580 VMX_VMCS32_GUEST_LDTR_LIMIT,
581 VMX_VMCS32_GUEST_TR_LIMIT,
582 VMX_VMCS32_GUEST_GDTR_LIMIT,
583 VMX_VMCS32_GUEST_IDTR_LIMIT,
584 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
585 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
586 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
587 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
588 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
589 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS,
590 VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS,
591 VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS,
592 VMX_VMCS32_GUEST_INT_STATE,
593 VMX_VMCS32_GUEST_ACTIVITY_STATE,
594 VMX_VMCS32_GUEST_SMBASE,
595 VMX_VMCS32_GUEST_SYSENTER_CS,
596 VMX_VMCS32_PREEMPT_TIMER_VALUE,
597
598 /* 32-bit host-state fields. */
599 VMX_VMCS32_HOST_SYSENTER_CS,
600
601 /* Natural-width control fields. */
602 VMX_VMCS_CTRL_CR0_MASK,
603 VMX_VMCS_CTRL_CR4_MASK,
604 VMX_VMCS_CTRL_CR0_READ_SHADOW,
605 VMX_VMCS_CTRL_CR4_READ_SHADOW,
606 VMX_VMCS_CTRL_CR3_TARGET_VAL0,
607 VMX_VMCS_CTRL_CR3_TARGET_VAL1,
608 VMX_VMCS_CTRL_CR3_TARGET_VAL2,
609 VMX_VMCS_CTRL_CR3_TARGET_VAL3,
610
611 /* Natural-width read-only data fields. */
612 VMX_VMCS_RO_EXIT_QUALIFICATION,
613 VMX_VMCS_RO_IO_RCX,
614 VMX_VMCS_RO_IO_RSI,
615 VMX_VMCS_RO_IO_RDI,
616 VMX_VMCS_RO_IO_RIP,
617 VMX_VMCS_RO_GUEST_LINEAR_ADDR,
618
619 /* Natural-width guest-state field */
620 VMX_VMCS_GUEST_CR0,
621 VMX_VMCS_GUEST_CR3,
622 VMX_VMCS_GUEST_CR4,
623 VMX_VMCS_GUEST_ES_BASE,
624 VMX_VMCS_GUEST_CS_BASE,
625 VMX_VMCS_GUEST_SS_BASE,
626 VMX_VMCS_GUEST_DS_BASE,
627 VMX_VMCS_GUEST_FS_BASE,
628 VMX_VMCS_GUEST_GS_BASE,
629 VMX_VMCS_GUEST_LDTR_BASE,
630 VMX_VMCS_GUEST_TR_BASE,
631 VMX_VMCS_GUEST_GDTR_BASE,
632 VMX_VMCS_GUEST_IDTR_BASE,
633 VMX_VMCS_GUEST_DR7,
634 VMX_VMCS_GUEST_RSP,
635 VMX_VMCS_GUEST_RIP,
636 VMX_VMCS_GUEST_RFLAGS,
637 VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS,
638 VMX_VMCS_GUEST_SYSENTER_ESP,
639 VMX_VMCS_GUEST_SYSENTER_EIP,
640
641 /* Natural-width host-state fields */
642 VMX_VMCS_HOST_CR0,
643 VMX_VMCS_HOST_CR3,
644 VMX_VMCS_HOST_CR4,
645 VMX_VMCS_HOST_FS_BASE,
646 VMX_VMCS_HOST_GS_BASE,
647 VMX_VMCS_HOST_TR_BASE,
648 VMX_VMCS_HOST_GDTR_BASE,
649 VMX_VMCS_HOST_IDTR_BASE,
650 VMX_VMCS_HOST_SYSENTER_ESP,
651 VMX_VMCS_HOST_SYSENTER_EIP,
652 VMX_VMCS_HOST_RSP,
653 VMX_VMCS_HOST_RIP
654};
655#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
656
657#ifdef VMX_USE_CACHED_VMCS_ACCESSES
658static const uint32_t g_aVmcsCacheSegBase[] =
659{
660 VMX_VMCS_GUEST_ES_BASE_CACHE_IDX,
661 VMX_VMCS_GUEST_CS_BASE_CACHE_IDX,
662 VMX_VMCS_GUEST_SS_BASE_CACHE_IDX,
663 VMX_VMCS_GUEST_DS_BASE_CACHE_IDX,
664 VMX_VMCS_GUEST_FS_BASE_CACHE_IDX,
665 VMX_VMCS_GUEST_GS_BASE_CACHE_IDX
666};
667AssertCompile(RT_ELEMENTS(g_aVmcsCacheSegBase) == X86_SREG_COUNT);
668#endif
669static const uint32_t g_aVmcsSegBase[] =
670{
671 VMX_VMCS_GUEST_ES_BASE,
672 VMX_VMCS_GUEST_CS_BASE,
673 VMX_VMCS_GUEST_SS_BASE,
674 VMX_VMCS_GUEST_DS_BASE,
675 VMX_VMCS_GUEST_FS_BASE,
676 VMX_VMCS_GUEST_GS_BASE
677};
678static const uint32_t g_aVmcsSegSel[] =
679{
680 VMX_VMCS16_GUEST_ES_SEL,
681 VMX_VMCS16_GUEST_CS_SEL,
682 VMX_VMCS16_GUEST_SS_SEL,
683 VMX_VMCS16_GUEST_DS_SEL,
684 VMX_VMCS16_GUEST_FS_SEL,
685 VMX_VMCS16_GUEST_GS_SEL
686};
687static const uint32_t g_aVmcsSegLimit[] =
688{
689 VMX_VMCS32_GUEST_ES_LIMIT,
690 VMX_VMCS32_GUEST_CS_LIMIT,
691 VMX_VMCS32_GUEST_SS_LIMIT,
692 VMX_VMCS32_GUEST_DS_LIMIT,
693 VMX_VMCS32_GUEST_FS_LIMIT,
694 VMX_VMCS32_GUEST_GS_LIMIT
695};
696static const uint32_t g_aVmcsSegAttr[] =
697{
698 VMX_VMCS32_GUEST_ES_ACCESS_RIGHTS,
699 VMX_VMCS32_GUEST_CS_ACCESS_RIGHTS,
700 VMX_VMCS32_GUEST_SS_ACCESS_RIGHTS,
701 VMX_VMCS32_GUEST_DS_ACCESS_RIGHTS,
702 VMX_VMCS32_GUEST_FS_ACCESS_RIGHTS,
703 VMX_VMCS32_GUEST_GS_ACCESS_RIGHTS
704};
705AssertCompile(RT_ELEMENTS(g_aVmcsSegSel) == X86_SREG_COUNT);
706AssertCompile(RT_ELEMENTS(g_aVmcsSegLimit) == X86_SREG_COUNT);
707AssertCompile(RT_ELEMENTS(g_aVmcsSegBase) == X86_SREG_COUNT);
708AssertCompile(RT_ELEMENTS(g_aVmcsSegAttr) == X86_SREG_COUNT);
709
710#ifdef HMVMX_USE_FUNCTION_TABLE
711/**
712 * VMX_EXIT dispatch table.
713 */
714static const PFNVMXEXITHANDLER g_apfnVMExitHandlers[VMX_EXIT_MAX + 1] =
715{
716 /* 0 VMX_EXIT_XCPT_OR_NMI */ hmR0VmxExitXcptOrNmi,
717 /* 1 VMX_EXIT_EXT_INT */ hmR0VmxExitExtInt,
718 /* 2 VMX_EXIT_TRIPLE_FAULT */ hmR0VmxExitTripleFault,
719 /* 3 VMX_EXIT_INIT_SIGNAL */ hmR0VmxExitErrUnexpected,
720 /* 4 VMX_EXIT_SIPI */ hmR0VmxExitErrUnexpected,
721 /* 5 VMX_EXIT_IO_SMI */ hmR0VmxExitErrUnexpected,
722 /* 6 VMX_EXIT_SMI */ hmR0VmxExitErrUnexpected,
723 /* 7 VMX_EXIT_INT_WINDOW */ hmR0VmxExitIntWindow,
724 /* 8 VMX_EXIT_NMI_WINDOW */ hmR0VmxExitNmiWindow,
725 /* 9 VMX_EXIT_TASK_SWITCH */ hmR0VmxExitTaskSwitch,
726 /* 10 VMX_EXIT_CPUID */ hmR0VmxExitCpuid,
727 /* 11 VMX_EXIT_GETSEC */ hmR0VmxExitGetsec,
728 /* 12 VMX_EXIT_HLT */ hmR0VmxExitHlt,
729 /* 13 VMX_EXIT_INVD */ hmR0VmxExitInvd,
730 /* 14 VMX_EXIT_INVLPG */ hmR0VmxExitInvlpg,
731 /* 15 VMX_EXIT_RDPMC */ hmR0VmxExitRdpmc,
732 /* 16 VMX_EXIT_RDTSC */ hmR0VmxExitRdtsc,
733 /* 17 VMX_EXIT_RSM */ hmR0VmxExitErrUnexpected,
734 /* 18 VMX_EXIT_VMCALL */ hmR0VmxExitVmcall,
735#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
736 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitVmclear,
737 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitVmlaunch,
738 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitVmptrld,
739 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitVmptrst,
740 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitVmread,
741 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitVmresume,
742 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitVmwrite,
743 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitVmxoff,
744 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitVmxon,
745#else
746 /* 19 VMX_EXIT_VMCLEAR */ hmR0VmxExitSetPendingXcptUD,
747 /* 20 VMX_EXIT_VMLAUNCH */ hmR0VmxExitSetPendingXcptUD,
748 /* 21 VMX_EXIT_VMPTRLD */ hmR0VmxExitSetPendingXcptUD,
749 /* 22 VMX_EXIT_VMPTRST */ hmR0VmxExitSetPendingXcptUD,
750 /* 23 VMX_EXIT_VMREAD */ hmR0VmxExitSetPendingXcptUD,
751 /* 24 VMX_EXIT_VMRESUME */ hmR0VmxExitSetPendingXcptUD,
752 /* 25 VMX_EXIT_VMWRITE */ hmR0VmxExitSetPendingXcptUD,
753 /* 26 VMX_EXIT_VMXOFF */ hmR0VmxExitSetPendingXcptUD,
754 /* 27 VMX_EXIT_VMXON */ hmR0VmxExitSetPendingXcptUD,
755#endif
756 /* 28 VMX_EXIT_MOV_CRX */ hmR0VmxExitMovCRx,
757 /* 29 VMX_EXIT_MOV_DRX */ hmR0VmxExitMovDRx,
758 /* 30 VMX_EXIT_IO_INSTR */ hmR0VmxExitIoInstr,
759 /* 31 VMX_EXIT_RDMSR */ hmR0VmxExitRdmsr,
760 /* 32 VMX_EXIT_WRMSR */ hmR0VmxExitWrmsr,
761 /* 33 VMX_EXIT_ERR_INVALID_GUEST_STATE */ hmR0VmxExitErrInvalidGuestState,
762 /* 34 VMX_EXIT_ERR_MSR_LOAD */ hmR0VmxExitErrUnexpected,
763 /* 35 UNDEFINED */ hmR0VmxExitErrUnexpected,
764 /* 36 VMX_EXIT_MWAIT */ hmR0VmxExitMwait,
765 /* 37 VMX_EXIT_MTF */ hmR0VmxExitMtf,
766 /* 38 UNDEFINED */ hmR0VmxExitErrUnexpected,
767 /* 39 VMX_EXIT_MONITOR */ hmR0VmxExitMonitor,
768 /* 40 VMX_EXIT_PAUSE */ hmR0VmxExitPause,
769 /* 41 VMX_EXIT_ERR_MACHINE_CHECK */ hmR0VmxExitErrUnexpected,
770 /* 42 UNDEFINED */ hmR0VmxExitErrUnexpected,
771 /* 43 VMX_EXIT_TPR_BELOW_THRESHOLD */ hmR0VmxExitTprBelowThreshold,
772 /* 44 VMX_EXIT_APIC_ACCESS */ hmR0VmxExitApicAccess,
773 /* 45 VMX_EXIT_VIRTUALIZED_EOI */ hmR0VmxExitErrUnexpected,
774 /* 46 VMX_EXIT_GDTR_IDTR_ACCESS */ hmR0VmxExitErrUnexpected,
775 /* 47 VMX_EXIT_LDTR_TR_ACCESS */ hmR0VmxExitErrUnexpected,
776 /* 48 VMX_EXIT_EPT_VIOLATION */ hmR0VmxExitEptViolation,
777 /* 49 VMX_EXIT_EPT_MISCONFIG */ hmR0VmxExitEptMisconfig,
778 /* 50 VMX_EXIT_INVEPT */ hmR0VmxExitSetPendingXcptUD,
779 /* 51 VMX_EXIT_RDTSCP */ hmR0VmxExitRdtscp,
780 /* 52 VMX_EXIT_PREEMPT_TIMER */ hmR0VmxExitPreemptTimer,
781#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
782 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitInvvpid,
783#else
784 /* 53 VMX_EXIT_INVVPID */ hmR0VmxExitSetPendingXcptUD,
785#endif
786 /* 54 VMX_EXIT_WBINVD */ hmR0VmxExitWbinvd,
787 /* 55 VMX_EXIT_XSETBV */ hmR0VmxExitXsetbv,
788 /* 56 VMX_EXIT_APIC_WRITE */ hmR0VmxExitErrUnexpected,
789 /* 57 VMX_EXIT_RDRAND */ hmR0VmxExitErrUnexpected,
790 /* 58 VMX_EXIT_INVPCID */ hmR0VmxExitInvpcid,
791 /* 59 VMX_EXIT_VMFUNC */ hmR0VmxExitErrUnexpected,
792 /* 60 VMX_EXIT_ENCLS */ hmR0VmxExitErrUnexpected,
793 /* 61 VMX_EXIT_RDSEED */ hmR0VmxExitErrUnexpected,
794 /* 62 VMX_EXIT_PML_FULL */ hmR0VmxExitErrUnexpected,
795 /* 63 VMX_EXIT_XSAVES */ hmR0VmxExitErrUnexpected,
796 /* 64 VMX_EXIT_XRSTORS */ hmR0VmxExitErrUnexpected,
797 /* 65 UNDEFINED */ hmR0VmxExitErrUnexpected,
798 /* 66 VMX_EXIT_SPP_EVENT */ hmR0VmxExitErrUnexpected,
799 /* 67 VMX_EXIT_UMWAIT */ hmR0VmxExitErrUnexpected,
800 /* 68 VMX_EXIT_TPAUSE */ hmR0VmxExitErrUnexpected,
801};
802#endif /* HMVMX_USE_FUNCTION_TABLE */
803
804#if defined(VBOX_STRICT) && defined(LOG_ENABLED)
805static const char * const g_apszVmxInstrErrors[HMVMX_INSTR_ERROR_MAX + 1] =
806{
807 /* 0 */ "(Not Used)",
808 /* 1 */ "VMCALL executed in VMX root operation.",
809 /* 2 */ "VMCLEAR with invalid physical address.",
810 /* 3 */ "VMCLEAR with VMXON pointer.",
811 /* 4 */ "VMLAUNCH with non-clear VMCS.",
812 /* 5 */ "VMRESUME with non-launched VMCS.",
813 /* 6 */ "VMRESUME after VMXOFF",
814 /* 7 */ "VM-entry with invalid control fields.",
815 /* 8 */ "VM-entry with invalid host state fields.",
816 /* 9 */ "VMPTRLD with invalid physical address.",
817 /* 10 */ "VMPTRLD with VMXON pointer.",
818 /* 11 */ "VMPTRLD with incorrect revision identifier.",
819 /* 12 */ "VMREAD/VMWRITE from/to unsupported VMCS component.",
820 /* 13 */ "VMWRITE to read-only VMCS component.",
821 /* 14 */ "(Not Used)",
822 /* 15 */ "VMXON executed in VMX root operation.",
823 /* 16 */ "VM-entry with invalid executive-VMCS pointer.",
824 /* 17 */ "VM-entry with non-launched executing VMCS.",
825 /* 18 */ "VM-entry with executive-VMCS pointer not VMXON pointer.",
826 /* 19 */ "VMCALL with non-clear VMCS.",
827 /* 20 */ "VMCALL with invalid VM-exit control fields.",
828 /* 21 */ "(Not Used)",
829 /* 22 */ "VMCALL with incorrect MSEG revision identifier.",
830 /* 23 */ "VMXOFF under dual monitor treatment of SMIs and SMM.",
831 /* 24 */ "VMCALL with invalid SMM-monitor features.",
832 /* 25 */ "VM-entry with invalid VM-execution control fields in executive VMCS.",
833 /* 26 */ "VM-entry with events blocked by MOV SS.",
834 /* 27 */ "(Not Used)",
835 /* 28 */ "Invalid operand to INVEPT/INVVPID."
836};
837#endif /* VBOX_STRICT && LOG_ENABLED */
838
839
840/**
841 * Get the CR0 guest/host mask that does not change through the lifetime of a VM.
842 *
843 * Any bit set in this mask is owned by the host/hypervisor and would cause a
844 * VM-exit when modified by the guest.
845 *
846 * @returns The static CR0 guest/host mask.
847 * @param pVCpu The cross context virtual CPU structure.
848 */
849DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr0Mask(PCVMCPU pVCpu)
850{
851 /*
852 * Modifications to CR0 bits that VT-x ignores saving/restoring (CD, ET, NW) and
853 * to CR0 bits that we require for shadow paging (PG) by the guest must cause VM-exits.
854 */
855 /** @todo Avoid intercepting CR0.PE with unrestricted guest execution. Fix PGM
856 * enmGuestMode to be in-sync with the current mode. See @bugref{6398}
857 * and @bugref{6944}. */
858 PVM pVM = pVCpu->CTX_SUFF(pVM);
859 return ( X86_CR0_PE
860 | X86_CR0_NE
861 | (pVM->hm.s.fNestedPaging ? 0 : X86_CR0_WP)
862 | X86_CR0_PG
863 | X86_CR0_ET /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.ET */
864 | X86_CR0_CD /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.CD */
865 | X86_CR0_NW); /* Bit ignored on VM-entry and VM-exit. Don't let the guest modify the host CR0.NW */
866}
867
868
869/**
870 * Gets the CR4 guest/host mask that does not change through the lifetime of a VM.
871 *
872 * Any bit set in this mask is owned by the host/hypervisor and would cause a
873 * VM-exit when modified by the guest.
874 *
875 * @returns The static CR4 guest/host mask.
876 * @param pVCpu The cross context virtual CPU structure.
877 */
878DECL_FORCE_INLINE(uint64_t) hmR0VmxGetFixedCr4Mask(PCVMCPU pVCpu)
879{
880 /*
881 * We need to look at the host features here (for e.g. OSXSAVE, PCID) because
882 * these bits are reserved on hardware that does not support them. Since the
883 * CPU cannot refer to our virtual CPUID, we need to intercept CR4 changes to
884 * these bits and handle it depending on whether we expose them to the guest.
885 */
886 PVM pVM = pVCpu->CTX_SUFF(pVM);
887 bool const fXSaveRstor = pVM->cpum.ro.HostFeatures.fXSaveRstor;
888 bool const fPcid = pVM->cpum.ro.HostFeatures.fPcid;
889 return ( X86_CR4_VMXE
890 | X86_CR4_VME
891 | X86_CR4_PAE
892 | X86_CR4_PGE
893 | X86_CR4_PSE
894 | (fXSaveRstor ? X86_CR4_OSXSAVE : 0)
895 | (fPcid ? X86_CR4_PCIDE : 0));
896}
897
898
899/**
900 * Returns whether the the VM-exit MSR-store area differs from the VM-exit MSR-load
901 * area.
902 *
903 * @returns @c true if it's different, @c false otherwise.
904 * @param pVmcsInfo The VMCS info. object.
905 */
906DECL_FORCE_INLINE(bool) hmR0VmxIsSeparateExitMsrStoreAreaVmcs(PCVMXVMCSINFO pVmcsInfo)
907{
908 return RT_BOOL( pVmcsInfo->pvGuestMsrStore != pVmcsInfo->pvGuestMsrLoad
909 && pVmcsInfo->pvGuestMsrStore);
910}
911
912
913/**
914 * Checks whether one of the given Pin-based VM-execution controls are set.
915 *
916 * @returns @c true if set, @c false otherwise.
917 * @param pVCpu The cross context virtual CPU structure.
918 * @param pVmxTransient The VMX-transient structure.
919 * @param uPinCtls The Pin-based VM-execution controls to check.
920 *
921 * @remarks This will not check merged controls when executing a nested-guest
922 * but the original control specified by the guest hypervisor.
923 */
924static bool hmR0VmxIsPinCtlsSet(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, uint32_t uPinCtls)
925{
926 if (!pVmxTransient->fIsNestedGuest)
927 {
928 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
929 return RT_BOOL(pVmcsInfo->u32PinCtls & uPinCtls);
930 }
931 return CPUMIsGuestVmxPinCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uPinCtls);
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 guest hypervisor has set any one of them.
962 */
963static void hmR0VmxRemoveProcCtlsVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uProcCtls)
964{
965#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
966 bool const fRemoveCtls = !pVmxTransient->fIsNestedGuest
967 ? true
968 : !CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT);
969#else
970 NOREF(pVCpu);
971 bool const fRemoveCtls = true;
972#endif
973 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
974 if ( fRemoveCtls
975 && (pVmcsInfo->u32ProcCtls & uProcCtls))
976 {
977 pVmcsInfo->u32ProcCtls &= ~uProcCtls;
978 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
979 AssertRC(rc);
980 }
981}
982
983
984/**
985 * Sets the TSC offset for the current VMCS.
986 *
987 * @param pVCpu The cross context virtual CPU structure.
988 * @param uTscOffset The TSC offset to set.
989 * @param pVmcsInfo The VMCS info. object.
990 */
991static void hmR0VmxSetTscOffsetVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t uTscOffset)
992{
993 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
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 * @returns VBox status code.
1008 * @param pVmxTransient The VMX-transient structure.
1009 * @param uXcptMask The exception(s) to add.
1010 */
1011static int hmR0VmxAddXcptInterceptMask(PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1012{
1013 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1014 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
1015 if ((uXcptBitmap & uXcptMask) != uXcptMask)
1016 {
1017 uXcptBitmap |= uXcptMask;
1018 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
1019 AssertRCReturn(rc, rc);
1020 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
1021 }
1022 return VINF_SUCCESS;
1023}
1024
1025
1026/**
1027 * Adds an exception to the exception bitmap and commits it to the current VMCS.
1028 *
1029 * @returns VBox status code.
1030 * @param pVmxTransient The VMX-transient structure.
1031 * @param uXcpt The exception to add.
1032 */
1033static int hmR0VmxAddXcptIntercept(PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1034{
1035 Assert(uXcpt <= X86_XCPT_LAST);
1036 return hmR0VmxAddXcptInterceptMask(pVmxTransient, RT_BIT_32(uXcpt));
1037}
1038
1039
1040/**
1041 * Remove one or more exceptions from the exception bitmap and commits it to the
1042 * current VMCS.
1043 *
1044 * This takes care of not removing the exception intercept if a nested-guest
1045 * requires the exception to be intercepted.
1046 *
1047 * @returns VBox status code.
1048 * @param pVCpu The cross context virtual CPU structure.
1049 * @param pVmxTransient The VMX-transient structure.
1050 * @param uXcptMask The exception(s) to remove.
1051 */
1052static int hmR0VmxRemoveXcptInterceptMask(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uXcptMask)
1053{
1054 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
1055 uint32_t u32XcptBitmap = pVmcsInfo->u32XcptBitmap;
1056 if (u32XcptBitmap & uXcptMask)
1057 {
1058#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1059 if (!pVmxTransient->fIsNestedGuest)
1060 { /* likely */ }
1061 else
1062 {
1063 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
1064 uXcptMask &= ~pVmcsNstGst->u32XcptBitmap;
1065 }
1066#endif
1067#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
1068 uXcptMask &= ~( RT_BIT(X86_XCPT_BP)
1069 | RT_BIT(X86_XCPT_DE)
1070 | RT_BIT(X86_XCPT_NM)
1071 | RT_BIT(X86_XCPT_TS)
1072 | RT_BIT(X86_XCPT_UD)
1073 | RT_BIT(X86_XCPT_NP)
1074 | RT_BIT(X86_XCPT_SS)
1075 | RT_BIT(X86_XCPT_GP)
1076 | RT_BIT(X86_XCPT_PF)
1077 | RT_BIT(X86_XCPT_MF));
1078#elif defined(HMVMX_ALWAYS_TRAP_PF)
1079 uXcptMask &= ~RT_BIT(X86_XCPT_PF);
1080#endif
1081 if (uXcptMask)
1082 {
1083 /* Validate we are not removing any essential exception intercepts. */
1084 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || !(uXcptMask & RT_BIT(X86_XCPT_PF))); RT_NOREF(pVCpu);
1085 Assert(!(uXcptMask & RT_BIT(X86_XCPT_DB)));
1086 Assert(!(uXcptMask & RT_BIT(X86_XCPT_AC)));
1087
1088 /* Remove it from the exception bitmap. */
1089 u32XcptBitmap &= ~uXcptMask;
1090
1091 /* Commit and update the cache if necessary. */
1092 if (pVmcsInfo->u32XcptBitmap != u32XcptBitmap)
1093 {
1094 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
1095 AssertRCReturn(rc, rc);
1096 pVmcsInfo->u32XcptBitmap = u32XcptBitmap;
1097 }
1098 }
1099 }
1100 return VINF_SUCCESS;
1101}
1102
1103
1104/**
1105 * Remove an exceptions from the exception bitmap and commits it to the current
1106 * VMCS.
1107 *
1108 * @returns VBox status code.
1109 * @param pVCpu The cross context virtual CPU structure.
1110 * @param pVmxTransient The VMX-transient structure.
1111 * @param uXcpt The exception to remove.
1112 */
1113static int hmR0VmxRemoveXcptIntercept(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uXcpt)
1114{
1115 return hmR0VmxRemoveXcptInterceptMask(pVCpu, pVmxTransient, RT_BIT(uXcpt));
1116}
1117
1118
1119/**
1120 * Loads the VMCS specified by the VMCS info. object.
1121 *
1122 * @returns VBox status code.
1123 * @param pVmcsInfo The VMCS info. object.
1124 *
1125 * @remarks Can be called with interrupts disabled.
1126 */
1127static int hmR0VmxLoadVmcs(PVMXVMCSINFO pVmcsInfo)
1128{
1129 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1130 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1131
1132 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysVmcs);
1133 if (RT_SUCCESS(rc))
1134 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1135 return rc;
1136}
1137
1138
1139/**
1140 * Clears the VMCS specified by the VMCS info. object.
1141 *
1142 * @returns VBox status code.
1143 * @param pVmcsInfo The VMCS info. object.
1144 *
1145 * @remarks Can be called with interrupts disabled.
1146 */
1147static int hmR0VmxClearVmcs(PVMXVMCSINFO pVmcsInfo)
1148{
1149 Assert(pVmcsInfo->HCPhysVmcs != 0 && pVmcsInfo->HCPhysVmcs != NIL_RTHCPHYS);
1150 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1151
1152 int rc = VMXClearVmcs(pVmcsInfo->HCPhysVmcs);
1153 if (RT_SUCCESS(rc))
1154 pVmcsInfo->fVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1155 return rc;
1156}
1157
1158
1159#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1160/**
1161 * Loads the shadow VMCS specified by the VMCS info. object.
1162 *
1163 * @returns VBox status code.
1164 * @param pVmcsInfo The VMCS info. object.
1165 *
1166 * @remarks Can be called with interrupts disabled.
1167 */
1168static int hmR0VmxLoadShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1169{
1170 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1171 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1172
1173 int rc = VMXLoadVmcs(pVmcsInfo->HCPhysShadowVmcs);
1174 if (RT_SUCCESS(rc))
1175 pVmcsInfo->fShadowVmcsState |= VMX_V_VMCS_LAUNCH_STATE_CURRENT;
1176 return rc;
1177}
1178
1179
1180/**
1181 * Clears the shadow VMCS specified by the VMCS info. object.
1182 *
1183 * @returns VBox status code.
1184 * @param pVmcsInfo The VMCS info. object.
1185 *
1186 * @remarks Can be called with interrupts disabled.
1187 */
1188static int hmR0VmxClearShadowVmcs(PVMXVMCSINFO pVmcsInfo)
1189{
1190 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1191 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
1192
1193 int rc = VMXClearVmcs(pVmcsInfo->HCPhysShadowVmcs);
1194 if (RT_SUCCESS(rc))
1195 pVmcsInfo->fShadowVmcsState = VMX_V_VMCS_LAUNCH_STATE_CLEAR;
1196 return rc;
1197}
1198
1199
1200/**
1201 * Switches from and to the specified VMCSes.
1202 *
1203 * @returns VBox status code.
1204 * @param pVmcsInfoFrom The VMCS info. object we are switching from.
1205 * @param pVmcsInfoTo The VMCS info. object we are switching to.
1206 *
1207 * @remarks Called with interrupts disabled.
1208 */
1209static int hmR0VmxSwitchVmcs(PVMXVMCSINFO pVmcsInfoFrom, PVMXVMCSINFO pVmcsInfoTo)
1210{
1211 /*
1212 * Clear the VMCS we are switching out if it has not already been cleared.
1213 * This will sync any CPU internal data back to the VMCS.
1214 */
1215 if (pVmcsInfoFrom->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1216 {
1217 int rc = hmR0VmxClearVmcs(pVmcsInfoFrom);
1218 if (RT_SUCCESS(rc))
1219 {
1220 /*
1221 * The shadow VMCS, if any, would not be active at this point since we
1222 * would have cleared it while importing the virtual hardware-virtualization
1223 * state as part the VMLAUNCH/VMRESUME VM-exit. Hence, there's no need to
1224 * clear the shadow VMCS here, just assert for safety.
1225 */
1226 Assert(!pVmcsInfoFrom->pvShadowVmcs || pVmcsInfoFrom->fShadowVmcsState == VMX_V_VMCS_LAUNCH_STATE_CLEAR);
1227 }
1228 else
1229 return rc;
1230 }
1231
1232 /*
1233 * Clear the VMCS we are switching to if it has not already been cleared.
1234 * This will initialize the VMCS launch state to "clear" required for loading it.
1235 *
1236 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
1237 */
1238 if (pVmcsInfoTo->fVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
1239 {
1240 int rc = hmR0VmxClearVmcs(pVmcsInfoTo);
1241 if (RT_SUCCESS(rc))
1242 { /* likely */ }
1243 else
1244 return rc;
1245 }
1246
1247 /*
1248 * Finally, load the VMCS we are switching to.
1249 */
1250 return hmR0VmxLoadVmcs(pVmcsInfoTo);
1251}
1252
1253
1254/**
1255 * Switches between the guest VMCS and the nested-guest VMCS as specified by the
1256 * caller.
1257 *
1258 * @returns VBox status code.
1259 * @param pVCpu The cross context virtual CPU structure.
1260 * @param fSwitchToNstGstVmcs Whether to switch to the nested-guest VMCS (pass
1261 * true) or guest VMCS (pass false).
1262 */
1263static int hmR0VmxSwitchToGstOrNstGstVmcs(PVMCPU pVCpu, bool fSwitchToNstGstVmcs)
1264{
1265 /* Ensure we have synced everything from the guest-CPU context to the VMCS before switching. */
1266 HMVMX_CPUMCTX_ASSERT(pVCpu, HMVMX_CPUMCTX_EXTRN_ALL);
1267
1268 PVMXVMCSINFO pVmcsInfoFrom;
1269 PVMXVMCSINFO pVmcsInfoTo;
1270 if (fSwitchToNstGstVmcs)
1271 {
1272 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfo;
1273 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1274 }
1275 else
1276 {
1277 pVmcsInfoFrom = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1278 pVmcsInfoTo = &pVCpu->hm.s.vmx.VmcsInfo;
1279 }
1280
1281 /*
1282 * Disable interrupts to prevent being preempted while we switch the current VMCS as the
1283 * preemption hook code path acquires the current VMCS.
1284 */
1285 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1286
1287 int rc = hmR0VmxSwitchVmcs(pVmcsInfoFrom, pVmcsInfoTo);
1288 if (RT_SUCCESS(rc))
1289 {
1290 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fSwitchToNstGstVmcs;
1291
1292 /*
1293 * If we are switching to a VMCS that was executed on a different host CPU or was
1294 * never executed before, flag that we need to export the host state before executing
1295 * guest/nested-guest code using hardware-assisted VMX.
1296 *
1297 * This could probably be done in a preemptible context since the preemption hook
1298 * will flag the necessary change in host context. However, since preemption is
1299 * already disabled and to avoid making assumptions about host specific code in
1300 * RTMpCpuId when called with preemption enabled, we'll do this while preemption is
1301 * disabled.
1302 */
1303 if (pVmcsInfoTo->idHostCpu == RTMpCpuId())
1304 { /* likely */ }
1305 else
1306 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE);
1307
1308 ASMSetFlags(fEFlags);
1309
1310 /*
1311 * We use a different VM-exit MSR-store areas for the guest and nested-guest. Hence,
1312 * flag that we need to update the host MSR values there. Even if we decide in the
1313 * future to share the VM-exit MSR-store area page between the guest and nested-guest,
1314 * if its content differs, we would have to update the host MSRs anyway.
1315 */
1316 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
1317 }
1318 else
1319 ASMSetFlags(fEFlags);
1320 return rc;
1321}
1322#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
1323
1324
1325/**
1326 * Updates the VM's last error record.
1327 *
1328 * If there was a VMX instruction error, reads the error data from the VMCS and
1329 * updates VCPU's last error record as well.
1330 *
1331 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
1332 * Can be NULL if @a rc is not VERR_VMX_UNABLE_TO_START_VM or
1333 * VERR_VMX_INVALID_VMCS_FIELD.
1334 * @param rc The error code.
1335 */
1336static void hmR0VmxUpdateErrorRecord(PVMCPU pVCpu, int rc)
1337{
1338 if ( rc == VERR_VMX_INVALID_VMCS_FIELD
1339 || rc == VERR_VMX_UNABLE_TO_START_VM)
1340 {
1341 AssertPtrReturnVoid(pVCpu);
1342 VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
1343 }
1344 pVCpu->CTX_SUFF(pVM)->hm.s.rcInit = rc;
1345}
1346
1347
1348#ifdef VBOX_STRICT
1349/**
1350 * Reads the VM-entry interruption-information field from the VMCS into the VMX
1351 * transient structure.
1352 *
1353 * @returns VBox status code.
1354 * @param pVmxTransient The VMX-transient structure.
1355 *
1356 * @remarks No-long-jump zone!!!
1357 */
1358DECLINLINE(int) hmR0VmxReadEntryIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1359{
1360 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &pVmxTransient->uEntryIntInfo);
1361 AssertRCReturn(rc, rc);
1362 return VINF_SUCCESS;
1363}
1364
1365
1366/**
1367 * Reads the VM-entry exception error code field from the VMCS into
1368 * the VMX transient structure.
1369 *
1370 * @returns VBox status code.
1371 * @param pVmxTransient The VMX-transient structure.
1372 *
1373 * @remarks No-long-jump zone!!!
1374 */
1375DECLINLINE(int) hmR0VmxReadEntryXcptErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1376{
1377 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &pVmxTransient->uEntryXcptErrorCode);
1378 AssertRCReturn(rc, rc);
1379 return VINF_SUCCESS;
1380}
1381
1382
1383/**
1384 * Reads the VM-entry exception error code field from the VMCS into
1385 * the VMX transient structure.
1386 *
1387 * @returns VBox status code.
1388 * @param pVmxTransient The VMX-transient structure.
1389 *
1390 * @remarks No-long-jump zone!!!
1391 */
1392DECLINLINE(int) hmR0VmxReadEntryInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1393{
1394 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &pVmxTransient->cbEntryInstr);
1395 AssertRCReturn(rc, rc);
1396 return VINF_SUCCESS;
1397}
1398#endif /* VBOX_STRICT */
1399
1400
1401/**
1402 * Reads the VM-exit interruption-information field from the VMCS into the VMX
1403 * transient structure.
1404 *
1405 * @returns VBox status code.
1406 * @param pVmxTransient The VMX-transient structure.
1407 */
1408DECLINLINE(int) hmR0VmxReadExitIntInfoVmcs(PVMXTRANSIENT pVmxTransient)
1409{
1410 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_INFO))
1411 {
1412 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pVmxTransient->uExitIntInfo);
1413 AssertRCReturn(rc,rc);
1414 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_INFO;
1415 }
1416 return VINF_SUCCESS;
1417}
1418
1419
1420/**
1421 * Reads the VM-exit interruption error code from the VMCS into the VMX
1422 * transient structure.
1423 *
1424 * @returns VBox status code.
1425 * @param pVmxTransient The VMX-transient structure.
1426 */
1427DECLINLINE(int) hmR0VmxReadExitIntErrorCodeVmcs(PVMXTRANSIENT pVmxTransient)
1428{
1429 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE))
1430 {
1431 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pVmxTransient->uExitIntErrorCode);
1432 AssertRCReturn(rc, rc);
1433 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INTERRUPTION_ERROR_CODE;
1434 }
1435 return VINF_SUCCESS;
1436}
1437
1438
1439/**
1440 * Reads the VM-exit instruction length field from the VMCS into the VMX
1441 * transient structure.
1442 *
1443 * @returns VBox status code.
1444 * @param pVmxTransient The VMX-transient structure.
1445 */
1446DECLINLINE(int) hmR0VmxReadExitInstrLenVmcs(PVMXTRANSIENT pVmxTransient)
1447{
1448 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_LEN))
1449 {
1450 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pVmxTransient->cbInstr);
1451 AssertRCReturn(rc, rc);
1452 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_LEN;
1453 }
1454 return VINF_SUCCESS;
1455}
1456
1457
1458/**
1459 * Reads the VM-exit instruction-information field from the VMCS into
1460 * the VMX transient structure.
1461 *
1462 * @returns VBox status code.
1463 * @param pVmxTransient The VMX-transient structure.
1464 */
1465DECLINLINE(int) hmR0VmxReadExitInstrInfoVmcs(PVMXTRANSIENT pVmxTransient)
1466{
1467 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_INSTR_INFO))
1468 {
1469 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pVmxTransient->ExitInstrInfo.u);
1470 AssertRCReturn(rc, rc);
1471 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_INSTR_INFO;
1472 }
1473 return VINF_SUCCESS;
1474}
1475
1476
1477/**
1478 * Reads the Exit Qualification from the VMCS into the VMX transient structure.
1479 *
1480 * @returns VBox status code.
1481 * @param pVCpu The cross context virtual CPU structure of the
1482 * calling EMT. (Required for the VMCS cache case.)
1483 * @param pVmxTransient The VMX-transient structure.
1484 */
1485DECLINLINE(int) hmR0VmxReadExitQualVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1486{
1487 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_EXIT_QUALIFICATION))
1488 {
1489 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pVmxTransient->uExitQual); NOREF(pVCpu);
1490 AssertRCReturn(rc, rc);
1491 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_EXIT_QUALIFICATION;
1492 }
1493 return VINF_SUCCESS;
1494}
1495
1496
1497/**
1498 * Reads the Guest-linear address from the VMCS into the VMX transient structure.
1499 *
1500 * @returns VBox status code.
1501 * @param pVCpu The cross context virtual CPU structure of the
1502 * calling EMT. (Required for the VMCS cache case.)
1503 * @param pVmxTransient The VMX-transient structure.
1504 */
1505DECLINLINE(int) hmR0VmxReadGuestLinearAddrVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
1506{
1507 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_GUEST_LINEAR_ADDR))
1508 {
1509 int rc = VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pVmxTransient->uGuestLinearAddr); NOREF(pVCpu);
1510 AssertRCReturn(rc, rc);
1511 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_GUEST_LINEAR_ADDR;
1512 }
1513 return VINF_SUCCESS;
1514}
1515
1516
1517/**
1518 * Reads the IDT-vectoring information field from the VMCS into the VMX
1519 * transient structure.
1520 *
1521 * @returns VBox status code.
1522 * @param pVmxTransient The VMX-transient structure.
1523 *
1524 * @remarks No-long-jump zone!!!
1525 */
1526DECLINLINE(int) hmR0VmxReadIdtVectoringInfoVmcs(PVMXTRANSIENT pVmxTransient)
1527{
1528 if (!(pVmxTransient->fVmcsFieldsRead & HMVMX_READ_IDT_VECTORING_INFO))
1529 {
1530 int rc = VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pVmxTransient->uIdtVectoringInfo);
1531 AssertRCReturn(rc, rc);
1532 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_INFO;
1533 }
1534 return VINF_SUCCESS;
1535}
1536
1537
1538/**
1539 * Reads the IDT-vectoring error code from the VMCS into the VMX
1540 * transient structure.
1541 *
1542 * @returns VBox status code.
1543 * @param pVmxTransient The VMX-transient structure.
1544 */
1545DECLINLINE(int) 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 AssertRCReturn(rc, rc);
1551 pVmxTransient->fVmcsFieldsRead |= HMVMX_READ_IDT_VECTORING_ERROR_CODE;
1552 }
1553 return VINF_SUCCESS;
1554}
1555
1556
1557/**
1558 * Enters VMX root mode operation on the current CPU.
1559 *
1560 * @returns VBox status code.
1561 * @param pVM The cross context VM structure. Can be
1562 * NULL, after a resume.
1563 * @param HCPhysCpuPage Physical address of the VMXON region.
1564 * @param pvCpuPage Pointer to the VMXON region.
1565 */
1566static int hmR0VmxEnterRootMode(PVM pVM, RTHCPHYS HCPhysCpuPage, void *pvCpuPage)
1567{
1568 Assert(HCPhysCpuPage && HCPhysCpuPage != NIL_RTHCPHYS);
1569 Assert(RT_ALIGN_T(HCPhysCpuPage, _4K, RTHCPHYS) == HCPhysCpuPage);
1570 Assert(pvCpuPage);
1571 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1572
1573 if (pVM)
1574 {
1575 /* Write the VMCS revision identifier to the VMXON region. */
1576 *(uint32_t *)pvCpuPage = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
1577 }
1578
1579 /* Paranoid: Disable interrupts as, in theory, interrupt handlers might mess with CR4. */
1580 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1581
1582 /* Enable the VMX bit in CR4 if necessary. */
1583 RTCCUINTREG const uOldCr4 = SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
1584
1585 /* Enter VMX root mode. */
1586 int rc = VMXEnable(HCPhysCpuPage);
1587 if (RT_FAILURE(rc))
1588 {
1589 if (!(uOldCr4 & X86_CR4_VMXE))
1590 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1591
1592 if (pVM)
1593 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
1594 }
1595
1596 /* Restore interrupts. */
1597 ASMSetFlags(fEFlags);
1598 return rc;
1599}
1600
1601
1602/**
1603 * Exits VMX root mode operation on the current CPU.
1604 *
1605 * @returns VBox status code.
1606 */
1607static int hmR0VmxLeaveRootMode(void)
1608{
1609 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
1610
1611 /* Paranoid: Disable interrupts as, in theory, interrupts handlers might mess with CR4. */
1612 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
1613
1614 /* If we're for some reason not in VMX root mode, then don't leave it. */
1615 RTCCUINTREG const uHostCr4 = ASMGetCR4();
1616
1617 int rc;
1618 if (uHostCr4 & X86_CR4_VMXE)
1619 {
1620 /* Exit VMX root mode and clear the VMX bit in CR4. */
1621 VMXDisable();
1622 SUPR0ChangeCR4(0 /* fOrMask */, ~X86_CR4_VMXE);
1623 rc = VINF_SUCCESS;
1624 }
1625 else
1626 rc = VERR_VMX_NOT_IN_VMX_ROOT_MODE;
1627
1628 /* Restore interrupts. */
1629 ASMSetFlags(fEFlags);
1630 return rc;
1631}
1632
1633
1634/**
1635 * Allocates and maps a physically contiguous page. The allocated page is
1636 * zero'd out (used by various VT-x structures).
1637 *
1638 * @returns IPRT status code.
1639 * @param pMemObj Pointer to the ring-0 memory object.
1640 * @param ppVirt Where to store the virtual address of the allocation.
1641 * @param pHCPhys Where to store the physical address of the allocation.
1642 */
1643static int hmR0VmxPageAllocZ(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1644{
1645 AssertPtr(pMemObj);
1646 AssertPtr(ppVirt);
1647 AssertPtr(pHCPhys);
1648 int rc = RTR0MemObjAllocCont(pMemObj, X86_PAGE_4K_SIZE, false /* fExecutable */);
1649 if (RT_FAILURE(rc))
1650 return rc;
1651 *ppVirt = RTR0MemObjAddress(*pMemObj);
1652 *pHCPhys = RTR0MemObjGetPagePhysAddr(*pMemObj, 0 /* iPage */);
1653 ASMMemZero32(*ppVirt, X86_PAGE_4K_SIZE);
1654 return VINF_SUCCESS;
1655}
1656
1657
1658/**
1659 * Frees and unmaps an allocated, physical page.
1660 *
1661 * @param pMemObj Pointer to the ring-0 memory object.
1662 * @param ppVirt Where to re-initialize the virtual address of allocation as
1663 * 0.
1664 * @param pHCPhys Where to re-initialize the physical address of the
1665 * allocation as 0.
1666 */
1667static void hmR0VmxPageFree(PRTR0MEMOBJ pMemObj, PRTR0PTR ppVirt, PRTHCPHYS pHCPhys)
1668{
1669 AssertPtr(pMemObj);
1670 AssertPtr(ppVirt);
1671 AssertPtr(pHCPhys);
1672 /* NULL is valid, accepted and ignored by the free function below. */
1673 RTR0MemObjFree(*pMemObj, true /* fFreeMappings */);
1674 *pMemObj = NIL_RTR0MEMOBJ;
1675 *ppVirt = NULL;
1676 *pHCPhys = NIL_RTHCPHYS;
1677}
1678
1679
1680/**
1681 * Initializes a VMCS info. object.
1682 *
1683 * @param pVmcsInfo The VMCS info. object.
1684 */
1685static void hmR0VmxInitVmcsInfo(PVMXVMCSINFO pVmcsInfo)
1686{
1687 memset(pVmcsInfo, 0, sizeof(*pVmcsInfo));
1688
1689 Assert(pVmcsInfo->hMemObjVmcs == NIL_RTR0MEMOBJ);
1690 Assert(pVmcsInfo->hMemObjShadowVmcs == NIL_RTR0MEMOBJ);
1691 Assert(pVmcsInfo->hMemObjMsrBitmap == NIL_RTR0MEMOBJ);
1692 Assert(pVmcsInfo->hMemObjGuestMsrLoad == NIL_RTR0MEMOBJ);
1693 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1694 Assert(pVmcsInfo->hMemObjHostMsrLoad == NIL_RTR0MEMOBJ);
1695 pVmcsInfo->HCPhysVmcs = NIL_RTHCPHYS;
1696 pVmcsInfo->HCPhysShadowVmcs = NIL_RTHCPHYS;
1697 pVmcsInfo->HCPhysMsrBitmap = NIL_RTHCPHYS;
1698 pVmcsInfo->HCPhysGuestMsrLoad = NIL_RTHCPHYS;
1699 pVmcsInfo->HCPhysGuestMsrStore = NIL_RTHCPHYS;
1700 pVmcsInfo->HCPhysHostMsrLoad = NIL_RTHCPHYS;
1701 pVmcsInfo->HCPhysVirtApic = NIL_RTHCPHYS;
1702 pVmcsInfo->HCPhysEPTP = NIL_RTHCPHYS;
1703 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
1704 pVmcsInfo->idHostCpu = NIL_RTCPUID;
1705}
1706
1707
1708/**
1709 * Frees the VT-x structures for a VMCS info. object.
1710 *
1711 * @param pVM The cross context VM structure.
1712 * @param pVmcsInfo The VMCS info. object.
1713 */
1714static void hmR0VmxFreeVmcsInfo(PVM pVM, PVMXVMCSINFO pVmcsInfo)
1715{
1716 hmR0VmxPageFree(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1717
1718#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1719 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1720 hmR0VmxPageFree(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1721#endif
1722
1723 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1724 hmR0VmxPageFree(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1725
1726 hmR0VmxPageFree(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad, &pVmcsInfo->HCPhysHostMsrLoad);
1727 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad, &pVmcsInfo->HCPhysGuestMsrLoad);
1728 hmR0VmxPageFree(&pVmcsInfo->hMemObjGuestMsrStore, &pVmcsInfo->pvGuestMsrStore, &pVmcsInfo->HCPhysGuestMsrStore);
1729
1730 hmR0VmxInitVmcsInfo(pVmcsInfo);
1731}
1732
1733
1734/**
1735 * Allocates the VT-x structures for a VMCS info. object.
1736 *
1737 * @returns VBox status code.
1738 * @param pVCpu The cross context virtual CPU structure.
1739 * @param pVmcsInfo The VMCS info. object.
1740 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
1741 */
1742static int hmR0VmxAllocVmcsInfo(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
1743{
1744 PVM pVM = pVCpu->CTX_SUFF(pVM);
1745
1746 /* Allocate the guest VM control structure (VMCS). */
1747 int rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjVmcs, &pVmcsInfo->pvVmcs, &pVmcsInfo->HCPhysVmcs);
1748 if (RT_SUCCESS(rc))
1749 {
1750 if (!fIsNstGstVmcs)
1751 {
1752#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1753 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1754 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjShadowVmcs, &pVmcsInfo->pvShadowVmcs, &pVmcsInfo->HCPhysShadowVmcs);
1755#endif
1756 if (RT_SUCCESS(rc))
1757 {
1758 /* Get the allocated virtual-APIC page from the virtual APIC device. */
1759 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
1760 && (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW))
1761 {
1762 rc = APICGetApicPageForCpu(pVCpu, &pVmcsInfo->HCPhysVirtApic, (PRTR0PTR)&pVmcsInfo->pbVirtApic,
1763 NULL /* pR3Ptr */, NULL /* pRCPtr */);
1764 }
1765 }
1766 }
1767 else
1768 {
1769 /* We don't yet support exposing VMCS shadowing to the guest. */
1770 Assert(pVmcsInfo->HCPhysShadowVmcs == NIL_RTHCPHYS);
1771 Assert(!pVmcsInfo->pvShadowVmcs);
1772
1773 /* Get the allocated virtual-APIC page from CPUM. */
1774 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
1775 {
1776 pVmcsInfo->pbVirtApic = (uint8_t *)CPUMGetGuestVmxVirtApicPage(pVCpu, &pVCpu->cpum.GstCtx,
1777 &pVmcsInfo->HCPhysVirtApic);
1778 Assert(pVmcsInfo->pbVirtApic);
1779 Assert(pVmcsInfo->HCPhysVirtApic && pVmcsInfo->HCPhysVirtApic != NIL_RTHCPHYS);
1780 }
1781 }
1782
1783 if (RT_SUCCESS(rc))
1784 {
1785 /*
1786 * Allocate the MSR-bitmap if supported by the CPU. The MSR-bitmap is for
1787 * transparent accesses of specific MSRs.
1788 *
1789 * If the condition for enabling MSR bitmaps changes here, don't forget to
1790 * update HMIsMsrBitmapActive().
1791 *
1792 * We don't share MSR bitmaps between the guest and nested-guest as we then
1793 * don't need to care about carefully restoring the guest MSR bitmap.
1794 * The guest visible nested-guest MSR bitmap needs to remain unchanged.
1795 * Hence, allocate a separate MSR bitmap for the guest and nested-guest.
1796 * We also don't need to re-initialize the nested-guest MSR bitmap here as
1797 * we do that later while merging VMCS.
1798 */
1799 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
1800 {
1801 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjMsrBitmap, &pVmcsInfo->pvMsrBitmap, &pVmcsInfo->HCPhysMsrBitmap);
1802 if ( RT_SUCCESS(rc)
1803 && !fIsNstGstVmcs)
1804 ASMMemFill32(pVmcsInfo->pvMsrBitmap, X86_PAGE_4K_SIZE, UINT32_C(0xffffffff));
1805 }
1806
1807 if (RT_SUCCESS(rc))
1808 {
1809 /*
1810 * Allocate the VM-entry MSR-load area for the guest MSRs.
1811 *
1812 * Similar to MSR-bitmaps, we do not share the auto MSR-load/store are between
1813 * the guest and nested-guest.
1814 */
1815 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjGuestMsrLoad, &pVmcsInfo->pvGuestMsrLoad,
1816 &pVmcsInfo->HCPhysGuestMsrLoad);
1817 if (RT_SUCCESS(rc))
1818 {
1819 /*
1820 * We use the same page for VM-entry MSR-load and VM-exit MSR store areas.
1821 * These contain the guest MSRs to load on VM-entry and store on VM-exit.
1822 */
1823 Assert(pVmcsInfo->hMemObjGuestMsrStore == NIL_RTR0MEMOBJ);
1824 pVmcsInfo->pvGuestMsrStore = pVmcsInfo->pvGuestMsrLoad;
1825 pVmcsInfo->HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrLoad;
1826
1827 /* Allocate the VM-exit MSR-load page for the host MSRs. */
1828 rc = hmR0VmxPageAllocZ(&pVmcsInfo->hMemObjHostMsrLoad, &pVmcsInfo->pvHostMsrLoad,
1829 &pVmcsInfo->HCPhysHostMsrLoad);
1830 }
1831 }
1832 }
1833 }
1834
1835 return rc;
1836}
1837
1838
1839/**
1840 * Free all VT-x structures for the VM.
1841 *
1842 * @returns IPRT status code.
1843 * @param pVM The cross context VM structure.
1844 */
1845static void hmR0VmxStructsFree(PVM pVM)
1846{
1847#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1848 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1849#endif
1850 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess, &pVM->hm.s.vmx.HCPhysApicAccess);
1851
1852#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1853 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1854 {
1855 RTMemFree(pVM->hm.s.vmx.paShadowVmcsFields);
1856 RTMemFree(pVM->hm.s.vmx.paShadowVmcsRoFields);
1857 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap, &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1858 hmR0VmxPageFree(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap, &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1859 }
1860#endif
1861
1862 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1863 {
1864 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1865 PVMXVMCSINFO pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
1866 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1867#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1868 if (pVM->cpum.ro.GuestFeatures.fVmx)
1869 {
1870 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
1871 hmR0VmxFreeVmcsInfo(pVM, pVmcsInfo);
1872 }
1873#endif
1874 }
1875}
1876
1877
1878/**
1879 * Allocate all VT-x structures for the VM.
1880 *
1881 * @returns IPRT status code.
1882 * @param pVM The cross context VM structure.
1883 */
1884static int hmR0VmxStructsAlloc(PVM pVM)
1885{
1886 /*
1887 * Sanity check the VMCS size reported by the CPU as we assume 4KB allocations.
1888 * The VMCS size cannot be more than 4096 bytes.
1889 *
1890 * See Intel spec. Appendix A.1 "Basic VMX Information".
1891 */
1892 uint32_t const cbVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_SIZE);
1893 if (cbVmcs <= X86_PAGE_4K_SIZE)
1894 { /* likely */ }
1895 else
1896 {
1897 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_INVALID_VMCS_SIZE;
1898 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
1899 }
1900
1901 /*
1902 * Initialize/check members up-front so we can cleanup en masse on allocation failures.
1903 */
1904#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1905 Assert(pVM->hm.s.vmx.hMemObjScratch == NIL_RTR0MEMOBJ);
1906 Assert(pVM->hm.s.vmx.pbScratch == NULL);
1907 pVM->hm.s.vmx.HCPhysScratch = NIL_RTHCPHYS;
1908#endif
1909
1910 Assert(pVM->hm.s.vmx.hMemObjApicAccess == NIL_RTR0MEMOBJ);
1911 Assert(pVM->hm.s.vmx.pbApicAccess == NULL);
1912 pVM->hm.s.vmx.HCPhysApicAccess = NIL_RTHCPHYS;
1913
1914 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1915 {
1916 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1917 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfo);
1918 hmR0VmxInitVmcsInfo(&pVCpu->hm.s.vmx.VmcsInfoNstGst);
1919 }
1920
1921 /*
1922 * Allocate per-VM VT-x structures.
1923 */
1924 int rc = VINF_SUCCESS;
1925#ifdef VBOX_WITH_CRASHDUMP_MAGIC
1926 /* Allocate crash-dump magic scratch page. */
1927 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjScratch, &pVM->hm.s.vmx.pbScratch, &pVM->hm.s.vmx.HCPhysScratch);
1928 if (RT_FAILURE(rc))
1929 {
1930 hmR0VmxStructsFree(pVM);
1931 return rc;
1932 }
1933 strcpy((char *)pVM->hm.s.vmx.pbScratch, "SCRATCH Magic");
1934 *(uint64_t *)(pVM->hm.s.vmx.pbScratch + 16) = UINT64_C(0xdeadbeefdeadbeef);
1935#endif
1936
1937 /* Allocate the APIC-access page for trapping APIC accesses from the guest. */
1938 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
1939 {
1940 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjApicAccess, (PRTR0PTR)&pVM->hm.s.vmx.pbApicAccess,
1941 &pVM->hm.s.vmx.HCPhysApicAccess);
1942 if (RT_FAILURE(rc))
1943 {
1944 hmR0VmxStructsFree(pVM);
1945 return rc;
1946 }
1947 }
1948
1949#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1950 /* Allocate the shadow VMCS fields array, VMREAD, VMWRITE bitmaps.. */
1951 if (pVM->hm.s.vmx.fUseVmcsShadowing)
1952 {
1953 Assert(!pVM->hm.s.vmx.cShadowVmcsFields);
1954 Assert(!pVM->hm.s.vmx.cShadowVmcsRoFields);
1955 pVM->hm.s.vmx.paShadowVmcsFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1956 pVM->hm.s.vmx.paShadowVmcsRoFields = (uint32_t *)RTMemAllocZ(sizeof(g_aVmcsFields));
1957 if (RT_LIKELY( pVM->hm.s.vmx.paShadowVmcsFields
1958 && pVM->hm.s.vmx.paShadowVmcsRoFields))
1959 {
1960 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmreadBitmap, &pVM->hm.s.vmx.pvVmreadBitmap,
1961 &pVM->hm.s.vmx.HCPhysVmreadBitmap);
1962 if (RT_SUCCESS(rc))
1963 {
1964 rc = hmR0VmxPageAllocZ(&pVM->hm.s.vmx.hMemObjVmwriteBitmap, &pVM->hm.s.vmx.pvVmwriteBitmap,
1965 &pVM->hm.s.vmx.HCPhysVmwriteBitmap);
1966 }
1967 }
1968 else
1969 rc = VERR_NO_MEMORY;
1970
1971 if (RT_FAILURE(rc))
1972 {
1973 hmR0VmxStructsFree(pVM);
1974 return rc;
1975 }
1976 }
1977#endif
1978
1979 /*
1980 * Initialize per-VCPU VT-x structures.
1981 */
1982 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
1983 {
1984 /* Allocate the guest VMCS structures. */
1985 PVMCPU pVCpu = &pVM->aCpus[idCpu];
1986 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
1987 if (RT_SUCCESS(rc))
1988 {
1989#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
1990 /* Allocate the nested-guest VMCS structures, when the VMX feature is exposed to the guest. */
1991 if (pVM->cpum.ro.GuestFeatures.fVmx)
1992 {
1993 rc = hmR0VmxAllocVmcsInfo(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
1994 if (RT_SUCCESS(rc))
1995 { /* likely */ }
1996 else
1997 break;
1998 }
1999#endif
2000 }
2001 else
2002 break;
2003 }
2004
2005 if (RT_FAILURE(rc))
2006 {
2007 hmR0VmxStructsFree(pVM);
2008 return rc;
2009 }
2010
2011 return VINF_SUCCESS;
2012}
2013
2014#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2015/**
2016 * Returns whether an MSR at the given MSR-bitmap offset is intercepted or not.
2017 *
2018 * @returns @c true if the MSR is intercepted, @c false otherwise.
2019 * @param pvMsrBitmap The MSR bitmap.
2020 * @param offMsr The MSR byte offset.
2021 * @param iBit The bit offset from the byte offset.
2022 */
2023DECLINLINE(bool) hmR0VmxIsMsrBitSet(const void *pvMsrBitmap, uint16_t offMsr, int32_t iBit)
2024{
2025 uint8_t const * const pbMsrBitmap = (uint8_t const * const)pvMsrBitmap;
2026 Assert(pbMsrBitmap);
2027 Assert(offMsr + (iBit >> 3) <= X86_PAGE_4K_SIZE);
2028 return ASMBitTest(pbMsrBitmap + offMsr, iBit);
2029}
2030#endif
2031
2032/**
2033 * Sets the permission bits for the specified MSR in the given MSR bitmap.
2034 *
2035 * If the passed VMCS is a nested-guest VMCS, this function ensures that the
2036 * read/write intercept is cleared from the MSR bitmap used for hardware-assisted
2037 * VMX execution of the nested-guest, only if nested-guest is also not intercepting
2038 * the read/write access of this MSR.
2039 *
2040 * @param pVCpu The cross context virtual CPU structure.
2041 * @param pVmcsInfo The VMCS info. object.
2042 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2043 * @param idMsr The MSR value.
2044 * @param fMsrpm The MSR permissions (see VMXMSRPM_XXX). This must
2045 * include both a read -and- a write permission!
2046 *
2047 * @sa CPUMGetVmxMsrPermission.
2048 * @remarks Can be called with interrupts disabled.
2049 */
2050static void hmR0VmxSetMsrPermission(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs, uint32_t idMsr, uint32_t fMsrpm)
2051{
2052 uint8_t *pbMsrBitmap = (uint8_t *)pVmcsInfo->pvMsrBitmap;
2053 Assert(pbMsrBitmap);
2054 Assert(VMXMSRPM_IS_FLAG_VALID(fMsrpm));
2055
2056 /*
2057 * MSR-bitmap Layout:
2058 * Byte index MSR range Interpreted as
2059 * 0x000 - 0x3ff 0x00000000 - 0x00001fff Low MSR read bits.
2060 * 0x400 - 0x7ff 0xc0000000 - 0xc0001fff High MSR read bits.
2061 * 0x800 - 0xbff 0x00000000 - 0x00001fff Low MSR write bits.
2062 * 0xc00 - 0xfff 0xc0000000 - 0xc0001fff High MSR write bits.
2063 *
2064 * A bit corresponding to an MSR within the above range causes a VM-exit
2065 * if the bit is 1 on executions of RDMSR/WRMSR. If an MSR falls out of
2066 * the MSR range, it always cause a VM-exit.
2067 *
2068 * See Intel spec. 24.6.9 "MSR-Bitmap Address".
2069 */
2070 uint16_t const offBitmapRead = 0;
2071 uint16_t const offBitmapWrite = 0x800;
2072 uint16_t offMsr;
2073 int32_t iBit;
2074 if (idMsr <= UINT32_C(0x00001fff))
2075 {
2076 offMsr = 0;
2077 iBit = idMsr;
2078 }
2079 else if (idMsr - UINT32_C(0xc0000000) <= UINT32_C(0x00001fff))
2080 {
2081 offMsr = 0x400;
2082 iBit = idMsr - UINT32_C(0xc0000000);
2083 }
2084 else
2085 AssertMsgFailedReturnVoid(("Invalid MSR %#RX32\n", idMsr));
2086
2087 /*
2088 * Set the MSR read permission.
2089 */
2090 uint16_t const offMsrRead = offBitmapRead + offMsr;
2091 Assert(offMsrRead + (iBit >> 3) < offBitmapWrite);
2092 if (fMsrpm & VMXMSRPM_ALLOW_RD)
2093 {
2094#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2095 bool const fClear = !fIsNstGstVmcs ? true
2096 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrRead, iBit);
2097#else
2098 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2099 bool const fClear = true;
2100#endif
2101 if (fClear)
2102 ASMBitClear(pbMsrBitmap + offMsrRead, iBit);
2103 }
2104 else
2105 ASMBitSet(pbMsrBitmap + offMsrRead, iBit);
2106
2107 /*
2108 * Set the MSR write permission.
2109 */
2110 uint16_t const offMsrWrite = offBitmapWrite + offMsr;
2111 Assert(offMsrWrite + (iBit >> 3) < X86_PAGE_4K_SIZE);
2112 if (fMsrpm & VMXMSRPM_ALLOW_WR)
2113 {
2114#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
2115 bool const fClear = !fIsNstGstVmcs ? true
2116 : !hmR0VmxIsMsrBitSet(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), offMsrWrite, iBit);
2117#else
2118 RT_NOREF2(pVCpu, fIsNstGstVmcs);
2119 bool const fClear = true;
2120#endif
2121 if (fClear)
2122 ASMBitClear(pbMsrBitmap + offMsrWrite, iBit);
2123 }
2124 else
2125 ASMBitSet(pbMsrBitmap + offMsrWrite, iBit);
2126}
2127
2128
2129/**
2130 * Updates the VMCS with the number of effective MSRs in the auto-load/store MSR
2131 * area.
2132 *
2133 * @returns VBox status code.
2134 * @param pVCpu The cross context virtual CPU structure.
2135 * @param pVmcsInfo The VMCS info. object.
2136 * @param cMsrs The number of MSRs.
2137 */
2138static int hmR0VmxSetAutoLoadStoreMsrCount(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t cMsrs)
2139{
2140 /* Shouldn't ever happen but there -is- a number. We're well within the recommended 512. */
2141 uint32_t const cMaxSupportedMsrs = VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc);
2142 if (RT_LIKELY(cMsrs < cMaxSupportedMsrs))
2143 {
2144 /* Commit the MSR counts to the VMCS and update the cache. */
2145 if (pVmcsInfo->cEntryMsrLoad != cMsrs)
2146 {
2147 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, cMsrs);
2148 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, cMsrs);
2149 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, cMsrs);
2150 AssertRCReturn(rc, rc);
2151
2152 pVmcsInfo->cEntryMsrLoad = cMsrs;
2153 pVmcsInfo->cExitMsrStore = cMsrs;
2154 pVmcsInfo->cExitMsrLoad = cMsrs;
2155 }
2156 return VINF_SUCCESS;
2157 }
2158
2159 LogRel(("Auto-load/store MSR count exceeded! cMsrs=%u MaxSupported=%u\n", cMsrs, cMaxSupportedMsrs));
2160 pVCpu->hm.s.u32HMError = VMX_UFC_INSUFFICIENT_GUEST_MSR_STORAGE;
2161 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
2162}
2163
2164
2165/**
2166 * Adds a new (or updates the value of an existing) guest/host MSR
2167 * pair to be swapped during the world-switch as part of the
2168 * auto-load/store MSR area in the VMCS.
2169 *
2170 * @returns VBox status code.
2171 * @param pVCpu The cross context virtual CPU structure.
2172 * @param pVmxTransient The VMX-transient structure.
2173 * @param idMsr The MSR.
2174 * @param uGuestMsrValue Value of the guest MSR.
2175 * @param fSetReadWrite Whether to set the guest read/write access of this
2176 * MSR (thus not causing a VM-exit).
2177 * @param fUpdateHostMsr Whether to update the value of the host MSR if
2178 * necessary.
2179 */
2180static int hmR0VmxAddAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr, uint64_t uGuestMsrValue,
2181 bool fSetReadWrite, bool fUpdateHostMsr)
2182{
2183 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2184 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2185 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2186 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2187 uint32_t i;
2188
2189 /* Paranoia. */
2190 Assert(pGuestMsrLoad);
2191
2192 LogFlowFunc(("pVCpu=%p idMsr=%#RX32 uGestMsrValue=%#RX64\n", pVCpu, idMsr, uGuestMsrValue));
2193
2194 /* Check if the MSR already exists in the VM-entry MSR-load area. */
2195 for (i = 0; i < cMsrs; i++)
2196 {
2197 if (pGuestMsrLoad[i].u32Msr == idMsr)
2198 break;
2199 }
2200
2201 bool fAdded = false;
2202 if (i == cMsrs)
2203 {
2204 /* The MSR does not exist, bump the MSR count to make room for the new MSR. */
2205 ++cMsrs;
2206 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2207 AssertMsgRCReturn(rc, ("Insufficient space to add MSR to VM-entry MSR-load/store area %u\n", idMsr), rc);
2208
2209 /* Set the guest to read/write this MSR without causing VM-exits. */
2210 if ( fSetReadWrite
2211 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
2212 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_ALLOW_RD_WR);
2213
2214 LogFlowFunc(("MSR added, cMsrs now %u\n", cMsrs));
2215 fAdded = true;
2216 }
2217
2218 /* Update the MSR value for the newly added or already existing MSR. */
2219 pGuestMsrLoad[i].u32Msr = idMsr;
2220 pGuestMsrLoad[i].u64Value = uGuestMsrValue;
2221
2222 /* Create the corresponding slot in the VM-exit MSR-store area if we use a different page. */
2223 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2224 {
2225 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2226 pGuestMsrStore[i].u32Msr = idMsr;
2227 pGuestMsrStore[i].u64Value = uGuestMsrValue;
2228 }
2229
2230 /* Update the corresponding slot in the host MSR area. */
2231 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2232 Assert(pHostMsr != pVmcsInfo->pvGuestMsrLoad);
2233 Assert(pHostMsr != pVmcsInfo->pvGuestMsrStore);
2234 pHostMsr[i].u32Msr = idMsr;
2235
2236 /*
2237 * Only if the caller requests to update the host MSR value AND we've newly added the
2238 * MSR to the host MSR area do we actually update the value. Otherwise, it will be
2239 * updated by hmR0VmxUpdateAutoLoadHostMsrs().
2240 *
2241 * We do this for performance reasons since reading MSRs may be quite expensive.
2242 */
2243 if (fAdded)
2244 {
2245 if (fUpdateHostMsr)
2246 {
2247 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2248 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2249 pHostMsr[i].u64Value = ASMRdMsr(idMsr);
2250 }
2251 else
2252 {
2253 /* Someone else can do the work. */
2254 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
2255 }
2256 }
2257 return VINF_SUCCESS;
2258}
2259
2260
2261/**
2262 * Removes a guest/host MSR pair to be swapped during the world-switch from the
2263 * auto-load/store MSR area in the VMCS.
2264 *
2265 * @returns VBox status code.
2266 * @param pVCpu The cross context virtual CPU structure.
2267 * @param pVmxTransient The VMX-transient structure.
2268 * @param idMsr The MSR.
2269 */
2270static int hmR0VmxRemoveAutoLoadStoreMsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t idMsr)
2271{
2272 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
2273 bool const fIsNstGstVmcs = pVmxTransient->fIsNestedGuest;
2274 PVMXAUTOMSR pGuestMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2275 uint32_t cMsrs = pVmcsInfo->cEntryMsrLoad;
2276
2277 LogFlowFunc(("pVCpu=%p idMsr=%#RX32\n", pVCpu, idMsr));
2278
2279 for (uint32_t i = 0; i < cMsrs; i++)
2280 {
2281 /* Find the MSR. */
2282 if (pGuestMsrLoad[i].u32Msr == idMsr)
2283 {
2284 /*
2285 * If it's the last MSR, we only need to reduce the MSR count.
2286 * If it's -not- the last MSR, copy the last MSR in place of it and reduce the MSR count.
2287 */
2288 if (i < cMsrs - 1)
2289 {
2290 /* Remove it from the VM-entry MSR-load area. */
2291 pGuestMsrLoad[i].u32Msr = pGuestMsrLoad[cMsrs - 1].u32Msr;
2292 pGuestMsrLoad[i].u64Value = pGuestMsrLoad[cMsrs - 1].u64Value;
2293
2294 /* Remove it from the VM-exit MSR-store area if it's in a different page. */
2295 if (hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo))
2296 {
2297 PVMXAUTOMSR pGuestMsrStore = (PVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2298 Assert(pGuestMsrStore[i].u32Msr == idMsr);
2299 pGuestMsrStore[i].u32Msr = pGuestMsrStore[cMsrs - 1].u32Msr;
2300 pGuestMsrStore[i].u64Value = pGuestMsrStore[cMsrs - 1].u64Value;
2301 }
2302
2303 /* Remove it from the VM-exit MSR-load area. */
2304 PVMXAUTOMSR pHostMsr = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2305 Assert(pHostMsr[i].u32Msr == idMsr);
2306 pHostMsr[i].u32Msr = pHostMsr[cMsrs - 1].u32Msr;
2307 pHostMsr[i].u64Value = pHostMsr[cMsrs - 1].u64Value;
2308 }
2309
2310 /* Reduce the count to reflect the removed MSR and bail. */
2311 --cMsrs;
2312 break;
2313 }
2314 }
2315
2316 /* Update the VMCS if the count changed (meaning the MSR was found and removed). */
2317 if (cMsrs != pVmcsInfo->cEntryMsrLoad)
2318 {
2319 int rc = hmR0VmxSetAutoLoadStoreMsrCount(pVCpu, pVmcsInfo, cMsrs);
2320 AssertRCReturn(rc, rc);
2321
2322 /* We're no longer swapping MSRs during the world-switch, intercept guest read/writes to them. */
2323 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2324 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, fIsNstGstVmcs, idMsr, VMXMSRPM_EXIT_RD | VMXMSRPM_EXIT_WR);
2325
2326 Log4Func(("Removed MSR %#RX32, cMsrs=%u\n", idMsr, cMsrs));
2327 return VINF_SUCCESS;
2328 }
2329
2330 return VERR_NOT_FOUND;
2331}
2332
2333
2334/**
2335 * Checks if the specified guest MSR is part of the VM-entry MSR-load area.
2336 *
2337 * @returns @c true if found, @c false otherwise.
2338 * @param pVmcsInfo The VMCS info. object.
2339 * @param idMsr The MSR to find.
2340 */
2341static bool hmR0VmxIsAutoLoadGuestMsr(PCVMXVMCSINFO pVmcsInfo, uint32_t idMsr)
2342{
2343 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2344 uint32_t const cMsrs = pVmcsInfo->cEntryMsrLoad;
2345 Assert(pMsrs);
2346 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
2347 for (uint32_t i = 0; i < cMsrs; i++)
2348 {
2349 if (pMsrs[i].u32Msr == idMsr)
2350 return true;
2351 }
2352 return false;
2353}
2354
2355
2356/**
2357 * Updates the value of all host MSRs in the VM-exit MSR-load area.
2358 *
2359 * @param pVCpu The cross context virtual CPU structure.
2360 * @param pVmcsInfo The VMCS info. object.
2361 *
2362 * @remarks No-long-jump zone!!!
2363 */
2364static void hmR0VmxUpdateAutoLoadHostMsrs(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2365{
2366 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2367
2368 PVMXAUTOMSR pHostMsrLoad = (PVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2369 uint32_t const cMsrs = pVmcsInfo->cExitMsrLoad;
2370 Assert(pHostMsrLoad);
2371 Assert(sizeof(*pHostMsrLoad) * cMsrs <= X86_PAGE_4K_SIZE);
2372 LogFlowFunc(("pVCpu=%p cMsrs=%u\n", pVCpu, cMsrs));
2373 for (uint32_t i = 0; i < cMsrs; i++)
2374 {
2375 /*
2376 * Performance hack for the host EFER MSR. We use the cached value rather than re-read it.
2377 * Strict builds will catch mismatches in hmR0VmxCheckAutoLoadStoreMsrs(). See @bugref{7368}.
2378 */
2379 if (pHostMsrLoad[i].u32Msr == MSR_K6_EFER)
2380 pHostMsrLoad[i].u64Value = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2381 else
2382 pHostMsrLoad[i].u64Value = ASMRdMsr(pHostMsrLoad[i].u32Msr);
2383 }
2384}
2385
2386
2387/**
2388 * Saves a set of host MSRs to allow read/write passthru access to the guest and
2389 * perform lazy restoration of the host MSRs while leaving VT-x.
2390 *
2391 * @param pVCpu The cross context virtual CPU structure.
2392 *
2393 * @remarks No-long-jump zone!!!
2394 */
2395static void hmR0VmxLazySaveHostMsrs(PVMCPU pVCpu)
2396{
2397 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2398
2399 /*
2400 * Note: If you're adding MSRs here, make sure to update the MSR-bitmap accesses in hmR0VmxSetupVmcsProcCtls().
2401 */
2402 if (!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST))
2403 {
2404 Assert(!(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)); /* Guest MSRs better not be loaded now. */
2405#if HC_ARCH_BITS == 64
2406 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2407 {
2408 pVCpu->hm.s.vmx.u64HostMsrLStar = ASMRdMsr(MSR_K8_LSTAR);
2409 pVCpu->hm.s.vmx.u64HostMsrStar = ASMRdMsr(MSR_K6_STAR);
2410 pVCpu->hm.s.vmx.u64HostMsrSfMask = ASMRdMsr(MSR_K8_SF_MASK);
2411 pVCpu->hm.s.vmx.u64HostMsrKernelGsBase = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
2412 }
2413#endif
2414 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_SAVED_HOST;
2415 }
2416}
2417
2418
2419/**
2420 * Checks whether the MSR belongs to the set of guest MSRs that we restore
2421 * lazily while leaving VT-x.
2422 *
2423 * @returns true if it does, false otherwise.
2424 * @param pVCpu The cross context virtual CPU structure.
2425 * @param idMsr The MSR to check.
2426 */
2427static bool hmR0VmxIsLazyGuestMsr(PCVMCPU pVCpu, uint32_t idMsr)
2428{
2429 NOREF(pVCpu);
2430#if HC_ARCH_BITS == 64
2431 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2432 {
2433 switch (idMsr)
2434 {
2435 case MSR_K8_LSTAR:
2436 case MSR_K6_STAR:
2437 case MSR_K8_SF_MASK:
2438 case MSR_K8_KERNEL_GS_BASE:
2439 return true;
2440 }
2441 }
2442#else
2443 RT_NOREF(pVCpu, idMsr);
2444#endif
2445 return false;
2446}
2447
2448
2449/**
2450 * Loads a set of guests MSRs to allow read/passthru to the guest.
2451 *
2452 * The name of this function is slightly confusing. This function does NOT
2453 * postpone loading, but loads the MSR right now. "hmR0VmxLazy" is simply a
2454 * common prefix for functions dealing with "lazy restoration" of the shared
2455 * MSRs.
2456 *
2457 * @param pVCpu The cross context virtual CPU structure.
2458 *
2459 * @remarks No-long-jump zone!!!
2460 */
2461static void hmR0VmxLazyLoadGuestMsrs(PVMCPU pVCpu)
2462{
2463 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2464 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2465
2466 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2467#if HC_ARCH_BITS == 64
2468 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2469 {
2470 /*
2471 * If the guest MSRs are not loaded -and- if all the guest MSRs are identical
2472 * to the MSRs on the CPU (which are the saved host MSRs, see assertion above) then
2473 * we can skip a few MSR writes.
2474 *
2475 * Otherwise, it implies either 1. they're not loaded, or 2. they're loaded but the
2476 * guest MSR values in the guest-CPU context might be different to what's currently
2477 * loaded in the CPU. In either case, we need to write the new guest MSR values to the
2478 * CPU, see @bugref{8728}.
2479 */
2480 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
2481 if ( !(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2482 && pCtx->msrKERNELGSBASE == pVCpu->hm.s.vmx.u64HostMsrKernelGsBase
2483 && pCtx->msrLSTAR == pVCpu->hm.s.vmx.u64HostMsrLStar
2484 && pCtx->msrSTAR == pVCpu->hm.s.vmx.u64HostMsrStar
2485 && pCtx->msrSFMASK == pVCpu->hm.s.vmx.u64HostMsrSfMask)
2486 {
2487#ifdef VBOX_STRICT
2488 Assert(ASMRdMsr(MSR_K8_KERNEL_GS_BASE) == pCtx->msrKERNELGSBASE);
2489 Assert(ASMRdMsr(MSR_K8_LSTAR) == pCtx->msrLSTAR);
2490 Assert(ASMRdMsr(MSR_K6_STAR) == pCtx->msrSTAR);
2491 Assert(ASMRdMsr(MSR_K8_SF_MASK) == pCtx->msrSFMASK);
2492#endif
2493 }
2494 else
2495 {
2496 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE);
2497 ASMWrMsr(MSR_K8_LSTAR, pCtx->msrLSTAR);
2498 ASMWrMsr(MSR_K6_STAR, pCtx->msrSTAR);
2499 ASMWrMsr(MSR_K8_SF_MASK, pCtx->msrSFMASK);
2500 }
2501 }
2502#endif
2503 pVCpu->hm.s.vmx.fLazyMsrs |= VMX_LAZY_MSRS_LOADED_GUEST;
2504}
2505
2506
2507/**
2508 * Performs lazy restoration of the set of host MSRs if they were previously
2509 * loaded with guest MSR values.
2510 *
2511 * @param pVCpu The cross context virtual CPU structure.
2512 *
2513 * @remarks No-long-jump zone!!!
2514 * @remarks The guest MSRs should have been saved back into the guest-CPU
2515 * context by hmR0VmxImportGuestState()!!!
2516 */
2517static void hmR0VmxLazyRestoreHostMsrs(PVMCPU pVCpu)
2518{
2519 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2520 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
2521
2522 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
2523 {
2524 Assert(pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_SAVED_HOST);
2525#if HC_ARCH_BITS == 64
2526 if (pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests)
2527 {
2528 ASMWrMsr(MSR_K8_LSTAR, pVCpu->hm.s.vmx.u64HostMsrLStar);
2529 ASMWrMsr(MSR_K6_STAR, pVCpu->hm.s.vmx.u64HostMsrStar);
2530 ASMWrMsr(MSR_K8_SF_MASK, pVCpu->hm.s.vmx.u64HostMsrSfMask);
2531 ASMWrMsr(MSR_K8_KERNEL_GS_BASE, pVCpu->hm.s.vmx.u64HostMsrKernelGsBase);
2532 }
2533#endif
2534 }
2535 pVCpu->hm.s.vmx.fLazyMsrs &= ~(VMX_LAZY_MSRS_LOADED_GUEST | VMX_LAZY_MSRS_SAVED_HOST);
2536}
2537
2538
2539/**
2540 * Verifies that our cached values of the VMCS fields are all consistent with
2541 * what's actually present in the VMCS.
2542 *
2543 * @returns VBox status code.
2544 * @retval VINF_SUCCESS if all our caches match their respective VMCS fields.
2545 * @retval VERR_VMX_VMCS_FIELD_CACHE_INVALID if a cache field doesn't match the
2546 * VMCS content. HMCPU error-field is
2547 * updated, see VMX_VCI_XXX.
2548 * @param pVCpu The cross context virtual CPU structure.
2549 * @param pVmcsInfo The VMCS info. object.
2550 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2551 */
2552static int hmR0VmxCheckVmcsCtls(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2553{
2554 const char * const pcszVmcs = fIsNstGstVmcs ? "Nested-guest VMCS" : "VMCS";
2555
2556 uint32_t u32Val;
2557 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
2558 AssertRCReturn(rc, rc);
2559 AssertMsgReturnStmt(pVmcsInfo->u32EntryCtls == u32Val,
2560 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32EntryCtls, u32Val),
2561 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_ENTRY,
2562 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2563
2564 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val);
2565 AssertRCReturn(rc, rc);
2566 AssertMsgReturnStmt(pVmcsInfo->u32ExitCtls == u32Val,
2567 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ExitCtls, u32Val),
2568 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_EXIT,
2569 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2570
2571 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val);
2572 AssertRCReturn(rc, rc);
2573 AssertMsgReturnStmt(pVmcsInfo->u32PinCtls == u32Val,
2574 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32PinCtls, u32Val),
2575 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PIN_EXEC,
2576 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2577
2578 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val);
2579 AssertRCReturn(rc, rc);
2580 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls == u32Val,
2581 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls, u32Val),
2582 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC,
2583 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2584
2585 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
2586 {
2587 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val);
2588 AssertRCReturn(rc, rc);
2589 AssertMsgReturnStmt(pVmcsInfo->u32ProcCtls2 == u32Val,
2590 ("%s controls mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32ProcCtls2, u32Val),
2591 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_PROC_EXEC2,
2592 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2593 }
2594
2595 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val);
2596 AssertRCReturn(rc, rc);
2597 AssertMsgReturnStmt(pVmcsInfo->u32XcptBitmap == u32Val,
2598 ("%s exception bitmap mismatch: Cache=%#RX32 VMCS=%#RX32\n", pcszVmcs, pVmcsInfo->u32XcptBitmap, u32Val),
2599 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_XCPT_BITMAP,
2600 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2601
2602 uint64_t u64Val;
2603 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_TSC_OFFSET_FULL, &u64Val);
2604 AssertRCReturn(rc, rc);
2605 AssertMsgReturnStmt(pVmcsInfo->u64TscOffset == u64Val,
2606 ("%s TSC offset mismatch: Cache=%#RX64 VMCS=%#RX64\n", pcszVmcs, pVmcsInfo->u64TscOffset, u64Val),
2607 pVCpu->hm.s.u32HMError = VMX_VCI_CTRL_TSC_OFFSET,
2608 VERR_VMX_VMCS_FIELD_CACHE_INVALID);
2609
2610 NOREF(pcszVmcs);
2611 return VINF_SUCCESS;
2612}
2613
2614
2615#ifdef VBOX_STRICT
2616/**
2617 * Verifies that our cached host EFER MSR value has not changed since we cached it.
2618 *
2619 * @param pVCpu The cross context virtual CPU structure.
2620 * @param pVmcsInfo The VMCS info. object.
2621 */
2622static void hmR0VmxCheckHostEferMsr(PCVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2623{
2624 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2625
2626 if (pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_LOAD_EFER_MSR)
2627 {
2628 uint64_t const uHostEferMsr = ASMRdMsr(MSR_K6_EFER);
2629 uint64_t const uHostEferMsrCache = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer;
2630 uint64_t uVmcsEferMsrVmcs;
2631 int rc = VMXReadVmcs64(VMX_VMCS64_HOST_EFER_FULL, &uVmcsEferMsrVmcs);
2632 AssertRC(rc);
2633
2634 AssertMsgReturnVoid(uHostEferMsr == uVmcsEferMsrVmcs,
2635 ("EFER Host/VMCS mismatch! host=%#RX64 vmcs=%#RX64\n", uHostEferMsr, uVmcsEferMsrVmcs));
2636 AssertMsgReturnVoid(uHostEferMsr == uHostEferMsrCache,
2637 ("EFER Host/Cache mismatch! host=%#RX64 cache=%#RX64\n", uHostEferMsr, uHostEferMsrCache));
2638 }
2639}
2640
2641
2642/**
2643 * Verifies whether the guest/host MSR pairs in the auto-load/store area in the
2644 * VMCS are correct.
2645 *
2646 * @param pVCpu The cross context virtual CPU structure.
2647 * @param pVmcsInfo The VMCS info. object.
2648 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
2649 */
2650static void hmR0VmxCheckAutoLoadStoreMsrs(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
2651{
2652 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
2653
2654 /* Read the various MSR-area counts from the VMCS. */
2655 uint32_t cEntryLoadMsrs;
2656 uint32_t cExitStoreMsrs;
2657 uint32_t cExitLoadMsrs;
2658 int rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &cEntryLoadMsrs); AssertRC(rc);
2659 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &cExitStoreMsrs); AssertRC(rc);
2660 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &cExitLoadMsrs); AssertRC(rc);
2661
2662 /* Verify all the MSR counts are the same. */
2663 Assert(cEntryLoadMsrs == cExitStoreMsrs);
2664 Assert(cExitStoreMsrs == cExitLoadMsrs);
2665 uint32_t const cMsrs = cExitLoadMsrs;
2666
2667 /* Verify the MSR counts do not exceed the maximum count supported by the hardware. */
2668 Assert(cMsrs < VMX_MISC_MAX_MSRS(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.u64Misc));
2669
2670 /* Verify the MSR counts are within the allocated page size. */
2671 Assert(sizeof(VMXAUTOMSR) * cMsrs <= X86_PAGE_4K_SIZE);
2672
2673 /* Verify the relevant contents of the MSR areas match. */
2674 PCVMXAUTOMSR pGuestMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrLoad;
2675 PCVMXAUTOMSR pGuestMsrStore = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
2676 PCVMXAUTOMSR pHostMsrLoad = (PCVMXAUTOMSR)pVmcsInfo->pvHostMsrLoad;
2677 bool const fSeparateExitMsrStorePage = hmR0VmxIsSeparateExitMsrStoreAreaVmcs(pVmcsInfo);
2678 for (uint32_t i = 0; i < cMsrs; i++)
2679 {
2680 /* Verify that the MSRs are paired properly and that the host MSR has the correct value. */
2681 if (fSeparateExitMsrStorePage)
2682 {
2683 AssertMsgReturnVoid(pGuestMsrLoad->u32Msr == pGuestMsrStore->u32Msr,
2684 ("GuestMsrLoad=%#RX32 GuestMsrStore=%#RX32 cMsrs=%u\n",
2685 pGuestMsrLoad->u32Msr, pGuestMsrStore->u32Msr, cMsrs));
2686 }
2687
2688 AssertMsgReturnVoid(pHostMsrLoad->u32Msr == pGuestMsrLoad->u32Msr,
2689 ("HostMsrLoad=%#RX32 GuestMsrLoad=%#RX32 cMsrs=%u\n",
2690 pHostMsrLoad->u32Msr, pGuestMsrLoad->u32Msr, cMsrs));
2691
2692 uint64_t const u64Msr = ASMRdMsr(pHostMsrLoad->u32Msr);
2693 AssertMsgReturnVoid(pHostMsrLoad->u64Value == u64Msr,
2694 ("u32Msr=%#RX32 VMCS Value=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2695 pHostMsrLoad->u32Msr, pHostMsrLoad->u64Value, u64Msr, cMsrs));
2696
2697 /* Verify that cached host EFER MSR matches what's loaded the CPU. */
2698 bool const fIsEferMsr = RT_BOOL(pHostMsrLoad->u32Msr == MSR_K6_EFER);
2699 if (fIsEferMsr)
2700 {
2701 AssertMsgReturnVoid(u64Msr == pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer,
2702 ("Cached=%#RX64 ASMRdMsr=%#RX64 cMsrs=%u\n",
2703 pVCpu->CTX_SUFF(pVM)->hm.s.vmx.u64HostMsrEfer, u64Msr, cMsrs));
2704 }
2705
2706 /* Verify that the accesses are as expected in the MSR bitmap for auto-load/store MSRs. */
2707 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
2708 {
2709 uint32_t const fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, pGuestMsrLoad->u32Msr);
2710 if (fIsEferMsr)
2711 {
2712 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_RD), ("Passthru read for EFER MSR!?\n"));
2713 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_EXIT_WR), ("Passthru write for EFER MSR!?\n"));
2714 }
2715 else
2716 {
2717 if (!fIsNstGstVmcs)
2718 {
2719 AssertMsgReturnVoid((fMsrpm & VMXMSRPM_ALLOW_RD_WR) == VMXMSRPM_ALLOW_RD_WR,
2720 ("u32Msr=%#RX32 cMsrs=%u No passthru read/write!\n", pGuestMsrLoad->u32Msr, cMsrs));
2721 }
2722 else
2723 {
2724 /*
2725 * A nested-guest VMCS must -also- allow read/write passthrough for the MSR for us to
2726 * execute a nested-guest with MSR passthrough.
2727 *
2728 * Check if the nested-guest MSR bitmap allows passthrough, and if so, assert that we
2729 * allow passthrough too.
2730 */
2731 void const *pvMsrBitmapNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
2732 Assert(pvMsrBitmapNstGst);
2733 uint32_t const fMsrpmNstGst = CPUMGetVmxMsrPermission(pvMsrBitmapNstGst, pGuestMsrLoad->u32Msr);
2734 AssertMsgReturnVoid(fMsrpm == fMsrpmNstGst,
2735 ("u32Msr=%#RX32 cMsrs=%u Permission mismatch fMsrpm=%#x fMsrpmNstGst=%#x!\n",
2736 pGuestMsrLoad->u32Msr, cMsrs, fMsrpm, fMsrpmNstGst));
2737 }
2738 }
2739 }
2740
2741 /* Move to the next MSR. */
2742 pHostMsrLoad++;
2743 pGuestMsrLoad++;
2744 pGuestMsrStore++;
2745 }
2746}
2747#endif /* VBOX_STRICT */
2748
2749
2750/**
2751 * Flushes the TLB using EPT.
2752 *
2753 * @returns VBox status code.
2754 * @param pVCpu The cross context virtual CPU structure of the calling
2755 * EMT. Can be NULL depending on @a enmTlbFlush.
2756 * @param pVmcsInfo The VMCS info. object. Can be NULL depending on @a
2757 * enmTlbFlush.
2758 * @param enmTlbFlush Type of flush.
2759 *
2760 * @remarks Caller is responsible for making sure this function is called only
2761 * when NestedPaging is supported and providing @a enmTlbFlush that is
2762 * supported by the CPU.
2763 * @remarks Can be called with interrupts disabled.
2764 */
2765static void hmR0VmxFlushEpt(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, VMXTLBFLUSHEPT enmTlbFlush)
2766{
2767 uint64_t au64Descriptor[2];
2768 if (enmTlbFlush == VMXTLBFLUSHEPT_ALL_CONTEXTS)
2769 au64Descriptor[0] = 0;
2770 else
2771 {
2772 Assert(pVCpu);
2773 Assert(pVmcsInfo);
2774 au64Descriptor[0] = pVmcsInfo->HCPhysEPTP;
2775 }
2776 au64Descriptor[1] = 0; /* MBZ. Intel spec. 33.3 "VMX Instructions" */
2777
2778 int rc = VMXR0InvEPT(enmTlbFlush, &au64Descriptor[0]);
2779 AssertMsg(rc == VINF_SUCCESS, ("VMXR0InvEPT %#x %#RHp failed. rc=%Rrc\n", enmTlbFlush, au64Descriptor[0], rc));
2780
2781 if ( RT_SUCCESS(rc)
2782 && pVCpu)
2783 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushNestedPaging);
2784}
2785
2786
2787/**
2788 * Flushes the TLB using VPID.
2789 *
2790 * @returns VBox status code.
2791 * @param pVCpu The cross context virtual CPU structure of the calling
2792 * EMT. Can be NULL depending on @a enmTlbFlush.
2793 * @param enmTlbFlush Type of flush.
2794 * @param GCPtr Virtual address of the page to flush (can be 0 depending
2795 * on @a enmTlbFlush).
2796 *
2797 * @remarks Can be called with interrupts disabled.
2798 */
2799static void hmR0VmxFlushVpid(PVMCPU pVCpu, VMXTLBFLUSHVPID enmTlbFlush, RTGCPTR GCPtr)
2800{
2801 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid);
2802
2803 uint64_t au64Descriptor[2];
2804 if (enmTlbFlush == VMXTLBFLUSHVPID_ALL_CONTEXTS)
2805 {
2806 au64Descriptor[0] = 0;
2807 au64Descriptor[1] = 0;
2808 }
2809 else
2810 {
2811 AssertPtr(pVCpu);
2812 AssertMsg(pVCpu->hm.s.uCurrentAsid != 0, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2813 AssertMsg(pVCpu->hm.s.uCurrentAsid <= UINT16_MAX, ("VMXR0InvVPID: invalid ASID %lu\n", pVCpu->hm.s.uCurrentAsid));
2814 au64Descriptor[0] = pVCpu->hm.s.uCurrentAsid;
2815 au64Descriptor[1] = GCPtr;
2816 }
2817
2818 int rc = VMXR0InvVPID(enmTlbFlush, &au64Descriptor[0]);
2819 AssertMsg(rc == VINF_SUCCESS,
2820 ("VMXR0InvVPID %#x %u %RGv failed with %Rrc\n", enmTlbFlush, pVCpu ? pVCpu->hm.s.uCurrentAsid : 0, GCPtr, rc));
2821
2822 if ( RT_SUCCESS(rc)
2823 && pVCpu)
2824 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushAsid);
2825 NOREF(rc);
2826}
2827
2828
2829/**
2830 * Invalidates a guest page by guest virtual address. Only relevant for EPT/VPID,
2831 * otherwise there is nothing really to invalidate.
2832 *
2833 * @returns VBox status code.
2834 * @param pVCpu The cross context virtual CPU structure.
2835 * @param GCVirt Guest virtual address of the page to invalidate.
2836 */
2837VMMR0DECL(int) VMXR0InvalidatePage(PVMCPU pVCpu, RTGCPTR GCVirt)
2838{
2839 AssertPtr(pVCpu);
2840 LogFlowFunc(("pVCpu=%p GCVirt=%RGv\n", pVCpu, GCVirt));
2841
2842 if (!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_TLB_FLUSH))
2843 {
2844 /*
2845 * We must invalidate the guest TLB entry in either case, we cannot ignore it even for
2846 * the EPT case. See @bugref{6043} and @bugref{6177}.
2847 *
2848 * Set the VMCPU_FF_TLB_FLUSH force flag and flush before VM-entry in hmR0VmxFlushTLB*()
2849 * as this function maybe called in a loop with individual addresses.
2850 */
2851 PVM pVM = pVCpu->CTX_SUFF(pVM);
2852 if (pVM->hm.s.vmx.fVpid)
2853 {
2854 bool fVpidFlush = RT_BOOL(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR);
2855
2856#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
2857 /*
2858 * Workaround Erratum BV75, AAJ159 and others that affect several Intel CPUs
2859 * where executing INVVPID outside 64-bit mode does not flush translations of
2860 * 64-bit linear addresses, see @bugref{6208#c72}.
2861 */
2862 if (RT_HI_U32(GCVirt))
2863 fVpidFlush = false;
2864#endif
2865
2866 if (fVpidFlush)
2867 {
2868 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_INDIV_ADDR, GCVirt);
2869 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbInvlpgVirt);
2870 }
2871 else
2872 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2873 }
2874 else if (pVM->hm.s.fNestedPaging)
2875 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
2876 }
2877
2878 return VINF_SUCCESS;
2879}
2880
2881
2882/**
2883 * Dummy placeholder for tagged-TLB flush handling before VM-entry. Used in the
2884 * case where neither EPT nor VPID is supported by the CPU.
2885 *
2886 * @param pHostCpu The HM physical-CPU structure.
2887 * @param pVCpu The cross context virtual CPU structure.
2888 *
2889 * @remarks Called with interrupts disabled.
2890 */
2891static void hmR0VmxFlushTaggedTlbNone(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
2892{
2893 AssertPtr(pVCpu);
2894 AssertPtr(pHostCpu);
2895
2896 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2897
2898 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2899 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2900 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2901 pVCpu->hm.s.fForceTLBFlush = false;
2902 return;
2903}
2904
2905
2906/**
2907 * Flushes the tagged-TLB entries for EPT+VPID CPUs as necessary.
2908 *
2909 * @param pHostCpu The HM physical-CPU structure.
2910 * @param pVCpu The cross context virtual CPU structure.
2911 * @param pVmcsInfo The VMCS info. object.
2912 *
2913 * @remarks All references to "ASID" in this function pertains to "VPID" in Intel's
2914 * nomenclature. The reason is, to avoid confusion in compare statements
2915 * since the host-CPU copies are named "ASID".
2916 *
2917 * @remarks Called with interrupts disabled.
2918 */
2919static void hmR0VmxFlushTaggedTlbBoth(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
2920{
2921#ifdef VBOX_WITH_STATISTICS
2922 bool fTlbFlushed = false;
2923# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { fTlbFlushed = true; } while (0)
2924# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { \
2925 if (!fTlbFlushed) \
2926 STAM_COUNTER_INC(&pVCpu->hm.s.StatNoFlushTlbWorldSwitch); \
2927 } while (0)
2928#else
2929# define HMVMX_SET_TAGGED_TLB_FLUSHED() do { } while (0)
2930# define HMVMX_UPDATE_FLUSH_SKIPPED_STAT() do { } while (0)
2931#endif
2932
2933 AssertPtr(pVCpu);
2934 AssertPtr(pHostCpu);
2935 Assert(pHostCpu->idCpu != NIL_RTCPUID);
2936
2937 PVM pVM = pVCpu->CTX_SUFF(pVM);
2938 AssertMsg(pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid,
2939 ("hmR0VmxFlushTaggedTlbBoth cannot be invoked unless NestedPaging & VPID are enabled."
2940 "fNestedPaging=%RTbool fVpid=%RTbool", pVM->hm.s.fNestedPaging, pVM->hm.s.vmx.fVpid));
2941
2942 /*
2943 * Force a TLB flush for the first world-switch if the current CPU differs from the one we
2944 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
2945 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
2946 * cannot reuse the current ASID anymore.
2947 */
2948 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
2949 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
2950 {
2951 ++pHostCpu->uCurrentAsid;
2952 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
2953 {
2954 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0. */
2955 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
2956 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
2957 }
2958
2959 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
2960 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
2961 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
2962
2963 /*
2964 * Flush by EPT when we get rescheduled to a new host CPU to ensure EPT-only tagged mappings are also
2965 * invalidated. We don't need to flush-by-VPID here as flushing by EPT covers it. See @bugref{6568}.
2966 */
2967 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2968 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
2969 HMVMX_SET_TAGGED_TLB_FLUSHED();
2970 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH);
2971 }
2972 else if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH)) /* Check for explicit TLB flushes. */
2973 {
2974 /*
2975 * Changes to the EPT paging structure by VMM requires flushing-by-EPT as the CPU
2976 * creates guest-physical (ie. only EPT-tagged) mappings while traversing the EPT
2977 * tables when EPT is in use. Flushing-by-VPID will only flush linear (only
2978 * VPID-tagged) and combined (EPT+VPID tagged) mappings but not guest-physical
2979 * mappings, see @bugref{6568}.
2980 *
2981 * See Intel spec. 28.3.2 "Creating and Using Cached Translation Information".
2982 */
2983 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVM->hm.s.vmx.enmTlbFlushEpt);
2984 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
2985 HMVMX_SET_TAGGED_TLB_FLUSHED();
2986 }
2987
2988 pVCpu->hm.s.fForceTLBFlush = false;
2989 HMVMX_UPDATE_FLUSH_SKIPPED_STAT();
2990
2991 Assert(pVCpu->hm.s.idLastCpu == pHostCpu->idCpu);
2992 Assert(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes);
2993 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
2994 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
2995 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
2996 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
2997 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
2998 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
2999 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3000
3001 /* Update VMCS with the VPID. */
3002 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3003 AssertRC(rc);
3004
3005#undef HMVMX_SET_TAGGED_TLB_FLUSHED
3006}
3007
3008
3009/**
3010 * Flushes the tagged-TLB entries for EPT CPUs as necessary.
3011 *
3012 * @param pHostCpu The HM physical-CPU structure.
3013 * @param pVCpu The cross context virtual CPU structure.
3014 * @param pVmcsInfo The VMCS info. object.
3015 *
3016 * @remarks Called with interrupts disabled.
3017 */
3018static void hmR0VmxFlushTaggedTlbEpt(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3019{
3020 AssertPtr(pVCpu);
3021 AssertPtr(pHostCpu);
3022 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3023 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked without NestedPaging."));
3024 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTaggedTlbEpt cannot be invoked with VPID."));
3025
3026 /*
3027 * Force a TLB flush for the first world-switch if the current CPU differs from the one we ran on last.
3028 * A change in the TLB flush count implies the host CPU is online after a suspend/resume.
3029 */
3030 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3031 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3032 {
3033 pVCpu->hm.s.fForceTLBFlush = true;
3034 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3035 }
3036
3037 /* Check for explicit TLB flushes. */
3038 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3039 {
3040 pVCpu->hm.s.fForceTLBFlush = true;
3041 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3042 }
3043
3044 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3045 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3046
3047 if (pVCpu->hm.s.fForceTLBFlush)
3048 {
3049 hmR0VmxFlushEpt(pVCpu, pVmcsInfo, pVCpu->CTX_SUFF(pVM)->hm.s.vmx.enmTlbFlushEpt);
3050 pVCpu->hm.s.fForceTLBFlush = false;
3051 }
3052}
3053
3054
3055/**
3056 * Flushes the tagged-TLB entries for VPID CPUs as necessary.
3057 *
3058 * @param pHostCpu The HM physical-CPU structure.
3059 * @param pVCpu The cross context virtual CPU structure.
3060 *
3061 * @remarks Called with interrupts disabled.
3062 */
3063static void hmR0VmxFlushTaggedTlbVpid(PHMPHYSCPU pHostCpu, PVMCPU pVCpu)
3064{
3065 AssertPtr(pVCpu);
3066 AssertPtr(pHostCpu);
3067 Assert(pHostCpu->idCpu != NIL_RTCPUID);
3068 AssertMsg(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid, ("hmR0VmxFlushTlbVpid cannot be invoked without VPID."));
3069 AssertMsg(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging, ("hmR0VmxFlushTlbVpid cannot be invoked with NestedPaging"));
3070
3071 /*
3072 * Force a TLB flush for the first world switch if the current CPU differs from the one we
3073 * ran on last. If the TLB flush count changed, another VM (VCPU rather) has hit the ASID
3074 * limit while flushing the TLB or the host CPU is online after a suspend/resume, so we
3075 * cannot reuse the current ASID anymore.
3076 */
3077 if ( pVCpu->hm.s.idLastCpu != pHostCpu->idCpu
3078 || pVCpu->hm.s.cTlbFlushes != pHostCpu->cTlbFlushes)
3079 {
3080 pVCpu->hm.s.fForceTLBFlush = true;
3081 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlbWorldSwitch);
3082 }
3083
3084 /* Check for explicit TLB flushes. */
3085 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_TLB_FLUSH))
3086 {
3087 /*
3088 * If we ever support VPID flush combinations other than ALL or SINGLE-context (see
3089 * hmR0VmxSetupTaggedTlb()) we would need to explicitly flush in this case (add an
3090 * fExplicitFlush = true here and change the pHostCpu->fFlushAsidBeforeUse check below to
3091 * include fExplicitFlush's too) - an obscure corner case.
3092 */
3093 pVCpu->hm.s.fForceTLBFlush = true;
3094 STAM_COUNTER_INC(&pVCpu->hm.s.StatFlushTlb);
3095 }
3096
3097 PVM pVM = pVCpu->CTX_SUFF(pVM);
3098 pVCpu->hm.s.idLastCpu = pHostCpu->idCpu;
3099 if (pVCpu->hm.s.fForceTLBFlush)
3100 {
3101 ++pHostCpu->uCurrentAsid;
3102 if (pHostCpu->uCurrentAsid >= pVM->hm.s.uMaxAsid)
3103 {
3104 pHostCpu->uCurrentAsid = 1; /* Wraparound to 1; host uses 0 */
3105 pHostCpu->cTlbFlushes++; /* All VCPUs that run on this host CPU must use a new VPID. */
3106 pHostCpu->fFlushAsidBeforeUse = true; /* All VCPUs that run on this host CPU must flush their new VPID before use. */
3107 }
3108
3109 pVCpu->hm.s.fForceTLBFlush = false;
3110 pVCpu->hm.s.cTlbFlushes = pHostCpu->cTlbFlushes;
3111 pVCpu->hm.s.uCurrentAsid = pHostCpu->uCurrentAsid;
3112 if (pHostCpu->fFlushAsidBeforeUse)
3113 {
3114 if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_SINGLE_CONTEXT)
3115 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_SINGLE_CONTEXT, 0 /* GCPtr */);
3116 else if (pVM->hm.s.vmx.enmTlbFlushVpid == VMXTLBFLUSHVPID_ALL_CONTEXTS)
3117 {
3118 hmR0VmxFlushVpid(pVCpu, VMXTLBFLUSHVPID_ALL_CONTEXTS, 0 /* GCPtr */);
3119 pHostCpu->fFlushAsidBeforeUse = false;
3120 }
3121 else
3122 {
3123 /* hmR0VmxSetupTaggedTlb() ensures we never get here. Paranoia. */
3124 AssertMsgFailed(("Unsupported VPID-flush context type.\n"));
3125 }
3126 }
3127 }
3128
3129 AssertMsg(pVCpu->hm.s.cTlbFlushes == pHostCpu->cTlbFlushes,
3130 ("Flush count mismatch for cpu %d (%u vs %u)\n", pHostCpu->idCpu, pVCpu->hm.s.cTlbFlushes, pHostCpu->cTlbFlushes));
3131 AssertMsg(pHostCpu->uCurrentAsid >= 1 && pHostCpu->uCurrentAsid < pVM->hm.s.uMaxAsid,
3132 ("Cpu[%u] uCurrentAsid=%u cTlbFlushes=%u pVCpu->idLastCpu=%u pVCpu->cTlbFlushes=%u\n", pHostCpu->idCpu,
3133 pHostCpu->uCurrentAsid, pHostCpu->cTlbFlushes, pVCpu->hm.s.idLastCpu, pVCpu->hm.s.cTlbFlushes));
3134 AssertMsg(pVCpu->hm.s.uCurrentAsid >= 1 && pVCpu->hm.s.uCurrentAsid < pVM->hm.s.uMaxAsid,
3135 ("Cpu[%u] pVCpu->uCurrentAsid=%u\n", pHostCpu->idCpu, pVCpu->hm.s.uCurrentAsid));
3136
3137 int rc = VMXWriteVmcs32(VMX_VMCS16_VPID, pVCpu->hm.s.uCurrentAsid);
3138 AssertRC(rc);
3139}
3140
3141
3142/**
3143 * Flushes the guest TLB entry based on CPU capabilities.
3144 *
3145 * @param pHostCpu The HM physical-CPU structure.
3146 * @param pVCpu The cross context virtual CPU structure.
3147 * @param pVmcsInfo The VMCS info. object.
3148 *
3149 * @remarks Called with interrupts disabled.
3150 */
3151static void hmR0VmxFlushTaggedTlb(PHMPHYSCPU pHostCpu, PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3152{
3153#ifdef HMVMX_ALWAYS_FLUSH_TLB
3154 VMCPU_FF_SET(pVCpu, VMCPU_FF_TLB_FLUSH);
3155#endif
3156 PVM pVM = pVCpu->CTX_SUFF(pVM);
3157 switch (pVM->hm.s.vmx.enmTlbFlushType)
3158 {
3159 case VMXTLBFLUSHTYPE_EPT_VPID: hmR0VmxFlushTaggedTlbBoth(pHostCpu, pVCpu, pVmcsInfo); break;
3160 case VMXTLBFLUSHTYPE_EPT: hmR0VmxFlushTaggedTlbEpt(pHostCpu, pVCpu, pVmcsInfo); break;
3161 case VMXTLBFLUSHTYPE_VPID: hmR0VmxFlushTaggedTlbVpid(pHostCpu, pVCpu); break;
3162 case VMXTLBFLUSHTYPE_NONE: hmR0VmxFlushTaggedTlbNone(pHostCpu, pVCpu); break;
3163 default:
3164 AssertMsgFailed(("Invalid flush-tag function identifier\n"));
3165 break;
3166 }
3167 /* Don't assert that VMCPU_FF_TLB_FLUSH should no longer be pending. It can be set by other EMTs. */
3168}
3169
3170
3171/**
3172 * Sets up the appropriate tagged TLB-flush level and handler for flushing guest
3173 * TLB entries from the host TLB before VM-entry.
3174 *
3175 * @returns VBox status code.
3176 * @param pVM The cross context VM structure.
3177 */
3178static int hmR0VmxSetupTaggedTlb(PVM pVM)
3179{
3180 /*
3181 * Determine optimal flush type for nested paging.
3182 * We cannot ignore EPT if no suitable flush-types is supported by the CPU as we've already setup
3183 * unrestricted guest execution (see hmR3InitFinalizeR0()).
3184 */
3185 if (pVM->hm.s.fNestedPaging)
3186 {
3187 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT)
3188 {
3189 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_SINGLE_CONTEXT)
3190 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_SINGLE_CONTEXT;
3191 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
3192 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_ALL_CONTEXTS;
3193 else
3194 {
3195 /* Shouldn't happen. EPT is supported but no suitable flush-types supported. */
3196 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3197 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_FLUSH_TYPE_UNSUPPORTED;
3198 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3199 }
3200
3201 /* Make sure the write-back cacheable memory type for EPT is supported. */
3202 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EMT_WB)))
3203 {
3204 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3205 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_MEM_TYPE_NOT_WB;
3206 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3207 }
3208
3209 /* EPT requires a page-walk length of 4. */
3210 if (RT_UNLIKELY(!(pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_PAGE_WALK_LENGTH_4)))
3211 {
3212 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3213 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_PAGE_WALK_LENGTH_UNSUPPORTED;
3214 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3215 }
3216 }
3217 else
3218 {
3219 /* Shouldn't happen. EPT is supported but INVEPT instruction is not supported. */
3220 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NOT_SUPPORTED;
3221 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_EPT_INVEPT_UNAVAILABLE;
3222 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3223 }
3224 }
3225
3226 /*
3227 * Determine optimal flush type for VPID.
3228 */
3229 if (pVM->hm.s.vmx.fVpid)
3230 {
3231 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID)
3232 {
3233 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT)
3234 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_SINGLE_CONTEXT;
3235 else if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_ALL_CONTEXTS)
3236 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_ALL_CONTEXTS;
3237 else
3238 {
3239 /* Neither SINGLE nor ALL-context flush types for VPID is supported by the CPU. Ignore VPID capability. */
3240 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_INDIV_ADDR)
3241 LogRelFunc(("Only INDIV_ADDR supported. Ignoring VPID.\n"));
3242 if (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVVPID_SINGLE_CONTEXT_RETAIN_GLOBALS)
3243 LogRelFunc(("Only SINGLE_CONTEXT_RETAIN_GLOBALS supported. Ignoring VPID.\n"));
3244 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3245 pVM->hm.s.vmx.fVpid = false;
3246 }
3247 }
3248 else
3249 {
3250 /* Shouldn't happen. VPID is supported but INVVPID is not supported by the CPU. Ignore VPID capability. */
3251 Log4Func(("VPID supported without INVEPT support. Ignoring VPID.\n"));
3252 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NOT_SUPPORTED;
3253 pVM->hm.s.vmx.fVpid = false;
3254 }
3255 }
3256
3257 /*
3258 * Setup the handler for flushing tagged-TLBs.
3259 */
3260 if (pVM->hm.s.fNestedPaging && pVM->hm.s.vmx.fVpid)
3261 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT_VPID;
3262 else if (pVM->hm.s.fNestedPaging)
3263 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_EPT;
3264 else if (pVM->hm.s.vmx.fVpid)
3265 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_VPID;
3266 else
3267 pVM->hm.s.vmx.enmTlbFlushType = VMXTLBFLUSHTYPE_NONE;
3268 return VINF_SUCCESS;
3269}
3270
3271
3272#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3273/**
3274 * Sets up the shadow VMCS fields arrays.
3275 *
3276 * This function builds arrays of VMCS fields to sync the shadow VMCS later while
3277 * executing the guest.
3278 *
3279 * @returns VBox status code.
3280 * @param pVM The cross context VM structure.
3281 */
3282static int hmR0VmxSetupShadowVmcsFieldsArrays(PVM pVM)
3283{
3284 /*
3285 * Paranoia. Ensure we haven't exposed the VMWRITE-All VMX feature to the guest
3286 * when the host does not support it.
3287 */
3288 bool const fGstVmwriteAll = pVM->cpum.ro.GuestFeatures.fVmxVmwriteAll;
3289 if ( !fGstVmwriteAll
3290 || (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL))
3291 { /* likely. */ }
3292 else
3293 {
3294 LogRelFunc(("VMX VMWRITE-All feature exposed to the guest but host CPU does not support it!\n"));
3295 pVM->aCpus[0].hm.s.u32HMError = VMX_UFC_GST_HOST_VMWRITE_ALL;
3296 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3297 }
3298
3299 uint32_t const cVmcsFields = RT_ELEMENTS(g_aVmcsFields);
3300 uint32_t cRwFields = 0;
3301 uint32_t cRoFields = 0;
3302 for (uint32_t i = 0; i < cVmcsFields; i++)
3303 {
3304 VMXVMCSFIELD VmcsField;
3305 VmcsField.u = g_aVmcsFields[i];
3306
3307 /*
3308 * We will be writing "FULL" (64-bit) fields while syncing the shadow VMCS.
3309 * Therefore, "HIGH" (32-bit portion of 64-bit) fields must not be included
3310 * in the shadow VMCS fields array as they would be redundant.
3311 *
3312 * If the VMCS field depends on a CPU feature that is not exposed to the guest,
3313 * we must not include it in the shadow VMCS fields array. Guests attempting to
3314 * VMREAD/VMWRITE such VMCS fields would cause a VM-exit and we shall emulate
3315 * the required behavior.
3316 */
3317 if ( VmcsField.n.fAccessType == VMX_VMCSFIELD_ACCESS_FULL
3318 && CPUMIsGuestVmxVmcsFieldValid(pVM, VmcsField.u))
3319 {
3320 /*
3321 * Read-only fields are placed in a separate array so that while syncing shadow
3322 * VMCS fields later (which is more performance critical) we can avoid branches.
3323 *
3324 * However, if the guest can write to all fields (including read-only fields),
3325 * we treat it a as read/write field. Otherwise, writing to these fields would
3326 * cause a VMWRITE instruction error while syncing the shadow VMCS .
3327 */
3328 if ( fGstVmwriteAll
3329 || !HMVmxIsVmcsFieldReadOnly(VmcsField.u))
3330 pVM->hm.s.vmx.paShadowVmcsFields[cRwFields++] = VmcsField.u;
3331 else
3332 pVM->hm.s.vmx.paShadowVmcsRoFields[cRoFields++] = VmcsField.u;
3333 }
3334 }
3335
3336 /* Update the counts. */
3337 pVM->hm.s.vmx.cShadowVmcsFields = cRwFields;
3338 pVM->hm.s.vmx.cShadowVmcsRoFields = cRoFields;
3339 return VINF_SUCCESS;
3340}
3341
3342
3343/**
3344 * Sets up the VMREAD and VMWRITE bitmaps.
3345 *
3346 * @param pVM The cross context VM structure.
3347 */
3348static void hmR0VmxSetupVmreadVmwriteBitmaps(PVM pVM)
3349{
3350 /*
3351 * By default, ensure guest attempts to acceses to any VMCS fields cause VM-exits.
3352 */
3353 uint32_t const cbBitmap = X86_PAGE_4K_SIZE;
3354 uint8_t *pbVmreadBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmreadBitmap;
3355 uint8_t *pbVmwriteBitmap = (uint8_t *)pVM->hm.s.vmx.pvVmwriteBitmap;
3356 ASMMemFill32(pbVmreadBitmap, cbBitmap, UINT32_C(0xffffffff));
3357 ASMMemFill32(pbVmwriteBitmap, cbBitmap, UINT32_C(0xffffffff));
3358
3359 /*
3360 * Skip intercepting VMREAD/VMWRITE to guest read/write fields in the
3361 * VMREAD and VMWRITE bitmaps.
3362 */
3363 {
3364 uint32_t const *paShadowVmcsFields = pVM->hm.s.vmx.paShadowVmcsFields;
3365 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
3366 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
3367 {
3368 uint32_t const uVmcsField = paShadowVmcsFields[i];
3369 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3370 Assert(uVmcsField >> 3 < cbBitmap);
3371 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3372 ASMBitClear(pbVmwriteBitmap + (uVmcsField >> 3), uVmcsField & 7);
3373 }
3374 }
3375
3376 /*
3377 * Skip intercepting VMREAD for guest read-only fields in the VMREAD bitmap
3378 * if the host supports VMWRITE to all supported VMCS fields.
3379 */
3380 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
3381 {
3382 uint32_t const *paShadowVmcsRoFields = pVM->hm.s.vmx.paShadowVmcsRoFields;
3383 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
3384 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
3385 {
3386 uint32_t const uVmcsField = paShadowVmcsRoFields[i];
3387 Assert(!(uVmcsField & VMX_VMCSFIELD_RSVD_MASK));
3388 Assert(uVmcsField >> 3 < cbBitmap);
3389 ASMBitClear(pbVmreadBitmap + (uVmcsField >> 3), uVmcsField & 7);
3390 }
3391 }
3392}
3393#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
3394
3395
3396/**
3397 * Sets up the virtual-APIC page address for the VMCS.
3398 *
3399 * @returns VBox status code.
3400 * @param pVCpu The cross context virtual CPU structure.
3401 * @param pVmcsInfo The VMCS info. object.
3402 */
3403DECLINLINE(int) hmR0VmxSetupVmcsVirtApicAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3404{
3405 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3406 RTHCPHYS const HCPhysVirtApic = pVmcsInfo->HCPhysVirtApic;
3407 Assert(HCPhysVirtApic != NIL_RTHCPHYS);
3408 Assert(!(HCPhysVirtApic & 0xfff)); /* Bits 11:0 MBZ. */
3409 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, HCPhysVirtApic);
3410}
3411
3412
3413/**
3414 * Sets up the MSR-bitmap address for the VMCS.
3415 *
3416 * @returns VBox status code.
3417 * @param pVCpu The cross context virtual CPU structure.
3418 * @param pVmcsInfo The VMCS info. object.
3419 */
3420DECLINLINE(int) hmR0VmxSetupVmcsMsrBitmapAddr(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
3421{
3422 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3423 RTHCPHYS const HCPhysMsrBitmap = pVmcsInfo->HCPhysMsrBitmap;
3424 Assert(HCPhysMsrBitmap != NIL_RTHCPHYS);
3425 Assert(!(HCPhysMsrBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3426 return VMXWriteVmcs64(VMX_VMCS64_CTRL_MSR_BITMAP_FULL, HCPhysMsrBitmap);
3427}
3428
3429
3430/**
3431 * Sets up the APIC-access page address for the VMCS.
3432 *
3433 * @returns VBox status code.
3434 * @param pVCpu The cross context virtual CPU structure.
3435 */
3436DECLINLINE(int) hmR0VmxSetupVmcsApicAccessAddr(PVMCPU pVCpu)
3437{
3438 RTHCPHYS const HCPhysApicAccess = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysApicAccess;
3439 Assert(HCPhysApicAccess != NIL_RTHCPHYS);
3440 Assert(!(HCPhysApicAccess & 0xfff)); /* Bits 11:0 MBZ. */
3441 return VMXWriteVmcs64(VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL, HCPhysApicAccess);
3442}
3443
3444
3445#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3446/**
3447 * Sets up the VMREAD bitmap address for the VMCS.
3448 *
3449 * @returns VBox status code.
3450 * @param pVCpu The cross context virtual CPU structure.
3451 */
3452DECLINLINE(int) hmR0VmxSetupVmcsVmreadBitmapAddr(PVMCPU pVCpu)
3453{
3454 RTHCPHYS const HCPhysVmreadBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmreadBitmap;
3455 Assert(HCPhysVmreadBitmap != NIL_RTHCPHYS);
3456 Assert(!(HCPhysVmreadBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3457 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMREAD_BITMAP_FULL, HCPhysVmreadBitmap);
3458}
3459
3460
3461/**
3462 * Sets up the VMWRITE bitmap address for the VMCS.
3463 *
3464 * @returns VBox status code.
3465 * @param pVCpu The cross context virtual CPU structure.
3466 */
3467DECLINLINE(int) hmR0VmxSetupVmcsVmwriteBitmapAddr(PVMCPU pVCpu)
3468{
3469 RTHCPHYS const HCPhysVmwriteBitmap = pVCpu->CTX_SUFF(pVM)->hm.s.vmx.HCPhysVmwriteBitmap;
3470 Assert(HCPhysVmwriteBitmap != NIL_RTHCPHYS);
3471 Assert(!(HCPhysVmwriteBitmap & 0xfff)); /* Bits 11:0 MBZ. */
3472 return VMXWriteVmcs64(VMX_VMCS64_CTRL_VMWRITE_BITMAP_FULL, HCPhysVmwriteBitmap);
3473}
3474#endif
3475
3476
3477/**
3478 * Sets up the VM-entry MSR load, VM-exit MSR-store and VM-exit MSR-load addresses
3479 * in the VMCS.
3480 *
3481 * @returns VBox status code.
3482 * @param pVCpu The cross context virtual CPU structure.
3483 * @param pVmcsInfo The VMCS info. object.
3484 */
3485DECLINLINE(int) hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3486{
3487 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
3488
3489 RTHCPHYS const HCPhysGuestMsrLoad = pVmcsInfo->HCPhysGuestMsrLoad;
3490 Assert(HCPhysGuestMsrLoad != NIL_RTHCPHYS);
3491 Assert(!(HCPhysGuestMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3492
3493 RTHCPHYS const HCPhysGuestMsrStore = pVmcsInfo->HCPhysGuestMsrStore;
3494 Assert(HCPhysGuestMsrStore != NIL_RTHCPHYS);
3495 Assert(!(HCPhysGuestMsrStore & 0xf)); /* Bits 3:0 MBZ. */
3496
3497 RTHCPHYS const HCPhysHostMsrLoad = pVmcsInfo->HCPhysHostMsrLoad;
3498 Assert(HCPhysHostMsrLoad != NIL_RTHCPHYS);
3499 Assert(!(HCPhysHostMsrLoad & 0xf)); /* Bits 3:0 MBZ. */
3500
3501 int rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL, HCPhysGuestMsrLoad);
3502 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL, HCPhysGuestMsrStore);
3503 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL, HCPhysHostMsrLoad);
3504 AssertRCReturn(rc, rc);
3505 return VINF_SUCCESS;
3506}
3507
3508
3509/**
3510 * Sets up MSR permissions in the MSR bitmap of a VMCS info. object.
3511 *
3512 * @param pVCpu The cross context virtual CPU structure.
3513 * @param pVmcsInfo The VMCS info. object.
3514 */
3515static void hmR0VmxSetupVmcsMsrPermissions(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3516{
3517 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS);
3518
3519 /*
3520 * The guest can access the following MSRs (read, write) without causing
3521 * VM-exits; they are loaded/stored automatically using fields in the VMCS.
3522 */
3523 PVM pVM = pVCpu->CTX_SUFF(pVM);
3524 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_CS, VMXMSRPM_ALLOW_RD_WR);
3525 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_ESP, VMXMSRPM_ALLOW_RD_WR);
3526 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SYSENTER_EIP, VMXMSRPM_ALLOW_RD_WR);
3527 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3528 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_FS_BASE, VMXMSRPM_ALLOW_RD_WR);
3529
3530 /*
3531 * The IA32_PRED_CMD and IA32_FLUSH_CMD MSRs are write-only and has no state
3532 * associated with then. We never need to intercept access (writes need to be
3533 * executed without causing a VM-exit, reads will #GP fault anyway).
3534 *
3535 * The IA32_SPEC_CTRL MSR is read/write and has state. We allow the guest to
3536 * read/write them. We swap the the guest/host MSR value using the
3537 * auto-load/store MSR area.
3538 */
3539 if (pVM->cpum.ro.GuestFeatures.fIbpb)
3540 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_PRED_CMD, VMXMSRPM_ALLOW_RD_WR);
3541 if (pVM->cpum.ro.GuestFeatures.fFlushCmd)
3542 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_FLUSH_CMD, VMXMSRPM_ALLOW_RD_WR);
3543 if (pVM->cpum.ro.GuestFeatures.fIbrs)
3544 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_IA32_SPEC_CTRL, VMXMSRPM_ALLOW_RD_WR);
3545
3546#if HC_ARCH_BITS == 64
3547 /*
3548 * Allow full read/write access for the following MSRs (mandatory for VT-x)
3549 * required for 64-bit guests.
3550 */
3551 if (pVM->hm.s.fAllow64BitGuests)
3552 {
3553 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_LSTAR, VMXMSRPM_ALLOW_RD_WR);
3554 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K6_STAR, VMXMSRPM_ALLOW_RD_WR);
3555 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_SF_MASK, VMXMSRPM_ALLOW_RD_WR);
3556 hmR0VmxSetMsrPermission(pVCpu, pVmcsInfo, false, MSR_K8_KERNEL_GS_BASE, VMXMSRPM_ALLOW_RD_WR);
3557 }
3558#endif
3559
3560 /*
3561 * IA32_EFER MSR is always intercepted, see @bugref{9180#c37}.
3562 */
3563#ifdef VBOX_STRICT
3564 Assert(pVmcsInfo->pvMsrBitmap);
3565 uint32_t const fMsrpmEfer = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, MSR_K6_EFER);
3566 Assert(fMsrpmEfer == VMXMSRPM_EXIT_RD_WR);
3567#endif
3568}
3569
3570
3571/**
3572 * Sets up pin-based VM-execution controls in the VMCS.
3573 *
3574 * @returns VBox status code.
3575 * @param pVCpu The cross context virtual CPU structure.
3576 * @param pVmcsInfo The VMCS info. object.
3577 */
3578static int hmR0VmxSetupVmcsPinCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3579{
3580 PVM pVM = pVCpu->CTX_SUFF(pVM);
3581 uint32_t fVal = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0; /* Bits set here must always be set. */
3582 uint32_t const fZap = pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1; /* Bits cleared here must always be cleared. */
3583
3584 fVal |= VMX_PIN_CTLS_EXT_INT_EXIT /* External interrupts cause a VM-exit. */
3585 | VMX_PIN_CTLS_NMI_EXIT; /* Non-maskable interrupts (NMIs) cause a VM-exit. */
3586
3587 if (pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_VIRT_NMI)
3588 fVal |= VMX_PIN_CTLS_VIRT_NMI; /* Use virtual NMIs and virtual-NMI blocking features. */
3589
3590 /* Enable the VMX-preemption timer. */
3591 if (pVM->hm.s.vmx.fUsePreemptTimer)
3592 {
3593 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_PREEMPT_TIMER);
3594 fVal |= VMX_PIN_CTLS_PREEMPT_TIMER;
3595 }
3596
3597#if 0
3598 /* Enable posted-interrupt processing. */
3599 if (pVM->hm.s.fPostedIntrs)
3600 {
3601 Assert(pVM->hm.s.vmx.Msrs.PinCtls.n.allowed1 & VMX_PIN_CTLS_POSTED_INT);
3602 Assert(pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_ACK_EXT_INT);
3603 fVal |= VMX_PIN_CTLS_POSTED_INT;
3604 }
3605#endif
3606
3607 if ((fVal & fZap) != fVal)
3608 {
3609 LogRelFunc(("Invalid pin-based VM-execution controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3610 pVM->hm.s.vmx.Msrs.PinCtls.n.allowed0, fVal, fZap));
3611 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PIN_EXEC;
3612 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3613 }
3614
3615 /* Commit it to the VMCS and update our cache. */
3616 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, fVal);
3617 AssertRCReturn(rc, rc);
3618 pVmcsInfo->u32PinCtls = fVal;
3619
3620 return VINF_SUCCESS;
3621}
3622
3623
3624/**
3625 * Sets up secondary processor-based VM-execution controls in the VMCS.
3626 *
3627 * @returns VBox status code.
3628 * @param pVCpu The cross context virtual CPU structure.
3629 * @param pVmcsInfo The VMCS info. object.
3630 */
3631static int hmR0VmxSetupVmcsProcCtls2(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3632{
3633 PVM pVM = pVCpu->CTX_SUFF(pVM);
3634 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0; /* Bits set here must be set in the VMCS. */
3635 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3636
3637 /* WBINVD causes a VM-exit. */
3638 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_WBINVD_EXIT)
3639 fVal |= VMX_PROC_CTLS2_WBINVD_EXIT;
3640
3641 /* Enable EPT (aka nested-paging). */
3642 if (pVM->hm.s.fNestedPaging)
3643 fVal |= VMX_PROC_CTLS2_EPT;
3644
3645 /* Enable the INVPCID instruction if we expose it to the guest and is supported
3646 by the hardware. Without this, guest executing INVPCID would cause a #UD. */
3647 if ( pVM->cpum.ro.GuestFeatures.fInvpcid
3648 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_INVPCID))
3649 fVal |= VMX_PROC_CTLS2_INVPCID;
3650
3651 /* Enable VPID. */
3652 if (pVM->hm.s.vmx.fVpid)
3653 fVal |= VMX_PROC_CTLS2_VPID;
3654
3655 /* Enable unrestricted guest execution. */
3656 if (pVM->hm.s.vmx.fUnrestrictedGuest)
3657 fVal |= VMX_PROC_CTLS2_UNRESTRICTED_GUEST;
3658
3659#if 0
3660 if (pVM->hm.s.fVirtApicRegs)
3661 {
3662 /* Enable APIC-register virtualization. */
3663 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_APIC_REG_VIRT);
3664 fVal |= VMX_PROC_CTLS2_APIC_REG_VIRT;
3665
3666 /* Enable virtual-interrupt delivery. */
3667 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_INTR_DELIVERY);
3668 fVal |= VMX_PROC_CTLS2_VIRT_INTR_DELIVERY;
3669 }
3670#endif
3671
3672 /* Virtualize-APIC accesses if supported by the CPU. The virtual-APIC page is
3673 where the TPR shadow resides. */
3674 /** @todo VIRT_X2APIC support, it's mutually exclusive with this. So must be
3675 * done dynamically. */
3676 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3677 {
3678 fVal |= VMX_PROC_CTLS2_VIRT_APIC_ACCESS;
3679 int rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3680 AssertRCReturn(rc, rc);
3681 }
3682
3683 /* Enable the RDTSCP instruction if we expose it to the guest and is supported
3684 by the hardware. Without this, guest executing RDTSCP would cause a #UD. */
3685 if ( pVM->cpum.ro.GuestFeatures.fRdTscP
3686 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_RDTSCP))
3687 fVal |= VMX_PROC_CTLS2_RDTSCP;
3688
3689 /* Enable Pause-Loop exiting. */
3690 if ( (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT)
3691 && pVM->hm.s.vmx.cPleGapTicks
3692 && pVM->hm.s.vmx.cPleWindowTicks)
3693 {
3694 fVal |= VMX_PROC_CTLS2_PAUSE_LOOP_EXIT;
3695
3696 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, pVM->hm.s.vmx.cPleGapTicks);
3697 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, pVM->hm.s.vmx.cPleWindowTicks);
3698 AssertRCReturn(rc, rc);
3699 }
3700
3701 if ((fVal & fZap) != fVal)
3702 {
3703 LogRelFunc(("Invalid secondary processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3704 pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed0, fVal, fZap));
3705 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC2;
3706 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3707 }
3708
3709 /* Commit it to the VMCS and update our cache. */
3710 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, fVal);
3711 AssertRCReturn(rc, rc);
3712 pVmcsInfo->u32ProcCtls2 = fVal;
3713
3714 return VINF_SUCCESS;
3715}
3716
3717
3718/**
3719 * Sets up processor-based VM-execution controls in the VMCS.
3720 *
3721 * @returns VBox status code.
3722 * @param pVCpu The cross context virtual CPU structure.
3723 * @param pVmcsInfo The VMCS info. object.
3724 */
3725static int hmR0VmxSetupVmcsProcCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3726{
3727 PVM pVM = pVCpu->CTX_SUFF(pVM);
3728
3729 uint32_t fVal = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
3730 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
3731
3732 fVal |= VMX_PROC_CTLS_HLT_EXIT /* HLT causes a VM-exit. */
3733 | VMX_PROC_CTLS_USE_TSC_OFFSETTING /* Use TSC-offsetting. */
3734 | VMX_PROC_CTLS_MOV_DR_EXIT /* MOV DRx causes a VM-exit. */
3735 | VMX_PROC_CTLS_UNCOND_IO_EXIT /* All IO instructions cause a VM-exit. */
3736 | VMX_PROC_CTLS_RDPMC_EXIT /* RDPMC causes a VM-exit. */
3737 | VMX_PROC_CTLS_MONITOR_EXIT /* MONITOR causes a VM-exit. */
3738 | VMX_PROC_CTLS_MWAIT_EXIT; /* MWAIT causes a VM-exit. */
3739
3740 /* We toggle VMX_PROC_CTLS_MOV_DR_EXIT later, check if it's not -always- needed to be set or clear. */
3741 if ( !(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MOV_DR_EXIT)
3742 || (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0 & VMX_PROC_CTLS_MOV_DR_EXIT))
3743 {
3744 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_MOV_DRX_EXIT;
3745 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3746 }
3747
3748 /* Without nested paging, INVLPG (also affects INVPCID) and MOV CR3 instructions should cause VM-exits. */
3749 if (!pVM->hm.s.fNestedPaging)
3750 {
3751 Assert(!pVM->hm.s.vmx.fUnrestrictedGuest);
3752 fVal |= VMX_PROC_CTLS_INVLPG_EXIT
3753 | VMX_PROC_CTLS_CR3_LOAD_EXIT
3754 | VMX_PROC_CTLS_CR3_STORE_EXIT;
3755 }
3756
3757 /* Use TPR shadowing if supported by the CPU. */
3758 if ( PDMHasApic(pVM)
3759 && pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_TPR_SHADOW)
3760 {
3761 fVal |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* CR8 reads from the Virtual-APIC page. */
3762 /* CR8 writes cause a VM-exit based on TPR threshold. */
3763 Assert(!(fVal & VMX_PROC_CTLS_CR8_STORE_EXIT));
3764 Assert(!(fVal & VMX_PROC_CTLS_CR8_LOAD_EXIT));
3765 int rc = hmR0VmxSetupVmcsVirtApicAddr(pVCpu, pVmcsInfo);
3766 AssertRCReturn(rc, rc);
3767 }
3768 else
3769 {
3770 /* Some 32-bit CPUs do not support CR8 load/store exiting as MOV CR8 is
3771 invalid on 32-bit Intel CPUs. Set this control only for 64-bit guests. */
3772 if (pVM->hm.s.fAllow64BitGuests)
3773 {
3774 fVal |= VMX_PROC_CTLS_CR8_STORE_EXIT /* CR8 reads cause a VM-exit. */
3775 | VMX_PROC_CTLS_CR8_LOAD_EXIT; /* CR8 writes cause a VM-exit. */
3776 }
3777 }
3778
3779 /* Use MSR-bitmaps if supported by the CPU. */
3780 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3781 {
3782 fVal |= VMX_PROC_CTLS_USE_MSR_BITMAPS;
3783 int rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3784 AssertRCReturn(rc, rc);
3785 }
3786
3787 /* Use the secondary processor-based VM-execution controls if supported by the CPU. */
3788 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3789 fVal |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
3790
3791 if ((fVal & fZap) != fVal)
3792 {
3793 LogRelFunc(("Invalid processor-based VM-execution controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
3794 pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0, fVal, fZap));
3795 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_PROC_EXEC;
3796 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3797 }
3798
3799 /* Commit it to the VMCS and update our cache. */
3800 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, fVal);
3801 AssertRCReturn(rc, rc);
3802 pVmcsInfo->u32ProcCtls = fVal;
3803
3804 /* Set up MSR permissions that don't change through the lifetime of the VM. */
3805 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3806 hmR0VmxSetupVmcsMsrPermissions(pVCpu, pVmcsInfo);
3807
3808 /* Set up secondary processor-based VM-execution controls if the CPU supports it. */
3809 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
3810 return hmR0VmxSetupVmcsProcCtls2(pVCpu, pVmcsInfo);
3811
3812 /* Sanity check, should not really happen. */
3813 if (RT_LIKELY(!pVM->hm.s.vmx.fUnrestrictedGuest))
3814 { /* likely */ }
3815 else
3816 {
3817 pVCpu->hm.s.u32HMError = VMX_UFC_INVALID_UX_COMBO;
3818 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
3819 }
3820
3821 /* Old CPUs without secondary processor-based VM-execution controls would end up here. */
3822 return VINF_SUCCESS;
3823}
3824
3825
3826/**
3827 * Sets up miscellaneous (everything other than Pin, Processor and secondary
3828 * Processor-based VM-execution) control fields in the VMCS.
3829 *
3830 * @returns VBox status code.
3831 * @param pVCpu The cross context virtual CPU structure.
3832 * @param pVmcsInfo The VMCS info. object.
3833 */
3834static int hmR0VmxSetupVmcsMiscCtls(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3835{
3836#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3837 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
3838 {
3839 int rc = hmR0VmxSetupVmcsVmreadBitmapAddr(pVCpu);
3840 rc |= hmR0VmxSetupVmcsVmwriteBitmapAddr(pVCpu);
3841 if (RT_SUCCESS(rc))
3842 { /* likely */ }
3843 else
3844 {
3845 LogRelFunc(("Failed to setup VMREAD/VMWRITE bitmap addresses. rc=%Rrc\n", rc));
3846 return rc;
3847 }
3848 }
3849#endif
3850
3851 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3852 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3853 if (RT_SUCCESS(rc))
3854 {
3855 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3856 if (RT_SUCCESS(rc))
3857 {
3858 uint64_t const u64Cr0Mask = hmR0VmxGetFixedCr0Mask(pVCpu);
3859 uint64_t const u64Cr4Mask = hmR0VmxGetFixedCr4Mask(pVCpu);
3860 rc = VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
3861 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
3862 if (RT_SUCCESS(rc))
3863 {
3864 pVmcsInfo->u64Cr0Mask = u64Cr0Mask;
3865 pVmcsInfo->u64Cr4Mask = u64Cr4Mask;
3866 return VINF_SUCCESS;
3867 }
3868 LogRelFunc(("Failed to initialize VMCS CR0/CR4 guest/host mask. rc=%Rrc\n", rc));
3869 }
3870 else
3871 LogRelFunc(("Failed to initialize VMCS auto-load/store MSR addresses. rc=%Rrc\n", rc));
3872 }
3873 else
3874 LogRelFunc(("Failed to initialize VMCS link pointer. rc=%Rrc\n", rc));
3875 return rc;
3876}
3877
3878
3879/**
3880 * Sets up the initial exception bitmap in the VMCS based on static conditions.
3881 *
3882 * We shall setup those exception intercepts that don't change during the
3883 * lifetime of the VM here. The rest are done dynamically while loading the
3884 * guest state.
3885 *
3886 * @returns VBox status code.
3887 * @param pVCpu The cross context virtual CPU structure.
3888 * @param pVmcsInfo The VMCS info. object.
3889 */
3890static int hmR0VmxSetupVmcsXcptBitmap(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3891{
3892 /*
3893 * The following exceptions are always intercepted:
3894 *
3895 * #AC - To prevent the guest from hanging the CPU.
3896 * #DB - To maintain the DR6 state even when intercepting DRx reads/writes and
3897 * recursive #DBs can cause a CPU hang.
3898 * #PF - To sync our shadow page tables when nested-paging is not used.
3899 */
3900 bool const fNestedPaging = pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging;
3901 uint32_t const uXcptBitmap = RT_BIT(X86_XCPT_AC)
3902 | RT_BIT(X86_XCPT_DB)
3903 | (fNestedPaging ? 0 : RT_BIT(X86_XCPT_PF));
3904
3905 /* Commit it to the VMCS. */
3906 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
3907 AssertRCReturn(rc, rc);
3908
3909 /* Update our cache of the exception bitmap. */
3910 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
3911 return VINF_SUCCESS;
3912}
3913
3914
3915#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
3916/**
3917 * Sets up the VMCS for executing a nested-guest using hardware-assisted VMX.
3918 *
3919 * @returns VBox status code.
3920 * @param pVCpu The cross context virtual CPU structure.
3921 * @param pVmcsInfo The VMCS info. object.
3922 */
3923static int hmR0VmxSetupVmcsCtlsNested(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
3924{
3925 PVM pVM = pVCpu->CTX_SUFF(pVM);
3926 Assert(pVmcsInfo->u64VmcsLinkPtr == NIL_RTHCPHYS);
3927 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
3928 if (RT_SUCCESS(rc))
3929 {
3930 rc = hmR0VmxSetupVmcsAutoLoadStoreMsrAddrs(pVCpu, pVmcsInfo);
3931 if (RT_SUCCESS(rc))
3932 {
3933 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_MSR_BITMAPS)
3934 rc = hmR0VmxSetupVmcsMsrBitmapAddr(pVCpu, pVmcsInfo);
3935 if (RT_SUCCESS(rc))
3936 {
3937 if (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
3938 rc = hmR0VmxSetupVmcsApicAccessAddr(pVCpu);
3939 if (RT_SUCCESS(rc))
3940 return VINF_SUCCESS;
3941
3942 LogRelFunc(("Failed to set up the APIC-access address in the nested-guest VMCS. rc=%Rrc\n", rc));
3943 }
3944 else
3945 LogRelFunc(("Failed to set up the MSR-bitmap address in the nested-guest VMCS. rc=%Rrc\n", rc));
3946 }
3947 else
3948 LogRelFunc(("Failed to set up the VMCS link pointer in the nested-guest VMCS. rc=%Rrc\n", rc));
3949 }
3950 else
3951 LogRelFunc(("Failed to set up the auto-load/store MSR addresses in the nested-guest VMCS. rc=%Rrc\n", rc));
3952
3953 return rc;
3954}
3955#endif
3956
3957
3958/**
3959 * Sets up the VMCS for executing a guest (or nested-guest) using hardware-assisted
3960 * VMX.
3961 *
3962 * @returns VBox status code.
3963 * @param pVCpu The cross context virtual CPU structure.
3964 * @param pVmcsInfo The VMCS info. object.
3965 * @param fIsNstGstVmcs Whether this is a nested-guest VMCS.
3966 */
3967static int hmR0VmxSetupVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, bool fIsNstGstVmcs)
3968{
3969 Assert(pVmcsInfo->pvVmcs);
3970 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
3971
3972 /* Set the CPU specified revision identifier at the beginning of the VMCS structure. */
3973 PVM pVM = pVCpu->CTX_SUFF(pVM);
3974 *(uint32_t *)pVmcsInfo->pvVmcs = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
3975 const char * const pszVmcs = fIsNstGstVmcs ? "nested-guest VMCS" : "guest VMCS";
3976
3977 LogFlowFunc(("\n"));
3978
3979 /*
3980 * Initialize the VMCS using VMCLEAR before loading the VMCS.
3981 * See Intel spec. 31.6 "Preparation And Launching A Virtual Machine".
3982 */
3983 int rc = hmR0VmxClearVmcs(pVmcsInfo);
3984 if (RT_SUCCESS(rc))
3985 {
3986 rc = hmR0VmxLoadVmcs(pVmcsInfo);
3987 if (RT_SUCCESS(rc))
3988 {
3989 if (!fIsNstGstVmcs)
3990 {
3991 rc = hmR0VmxSetupVmcsPinCtls(pVCpu, pVmcsInfo);
3992 if (RT_SUCCESS(rc))
3993 {
3994 rc = hmR0VmxSetupVmcsProcCtls(pVCpu, pVmcsInfo);
3995 if (RT_SUCCESS(rc))
3996 {
3997 rc = hmR0VmxSetupVmcsMiscCtls(pVCpu, pVmcsInfo);
3998 if (RT_SUCCESS(rc))
3999 {
4000 rc = hmR0VmxSetupVmcsXcptBitmap(pVCpu, pVmcsInfo);
4001 if (RT_SUCCESS(rc))
4002 {
4003#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4004 /*
4005 * If a shadow VMCS is allocated for the VMCS info. object, initialize the
4006 * VMCS revision ID and shadow VMCS indicator bit. Also, clear the VMCS
4007 * making it fit for use when VMCS shadowing is later enabled.
4008 */
4009 if (pVmcsInfo->pvShadowVmcs)
4010 {
4011 VMXVMCSREVID VmcsRevId;
4012 VmcsRevId.u = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID);
4013 VmcsRevId.n.fIsShadowVmcs = 1;
4014 *(uint32_t *)pVmcsInfo->pvShadowVmcs = VmcsRevId.u;
4015 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
4016 if (RT_SUCCESS(rc))
4017 { /* likely */ }
4018 else
4019 LogRelFunc(("Failed to initialize shadow VMCS. rc=%Rrc\n", rc));
4020 }
4021#endif
4022 }
4023 else
4024 LogRelFunc(("Failed to initialize exception bitmap. rc=%Rrc\n", rc));
4025 }
4026 else
4027 LogRelFunc(("Failed to setup miscellaneous controls. rc=%Rrc\n", rc));
4028 }
4029 else
4030 LogRelFunc(("Failed to setup processor-based VM-execution controls. rc=%Rrc\n", rc));
4031 }
4032 else
4033 LogRelFunc(("Failed to setup pin-based controls. rc=%Rrc\n", rc));
4034 }
4035 else
4036 {
4037#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4038 rc = hmR0VmxSetupVmcsCtlsNested(pVCpu, pVmcsInfo);
4039 if (RT_SUCCESS(rc))
4040 { /* likely */ }
4041 else
4042 LogRelFunc(("Failed to initialize nested-guest VMCS. rc=%Rrc\n", rc));
4043#else
4044 AssertFailed();
4045#endif
4046 }
4047 }
4048 else
4049 LogRelFunc(("Failed to load the %s. rc=%Rrc\n", rc, pszVmcs));
4050 }
4051 else
4052 LogRelFunc(("Failed to clear the %s. rc=%Rrc\n", rc, pszVmcs));
4053
4054 /* Sync any CPU internal VMCS data back into our VMCS in memory. */
4055 if (RT_SUCCESS(rc))
4056 {
4057 rc = hmR0VmxClearVmcs(pVmcsInfo);
4058 if (RT_SUCCESS(rc))
4059 { /* likely */ }
4060 else
4061 LogRelFunc(("Failed to clear the %s post setup. rc=%Rrc\n", rc, pszVmcs));
4062 }
4063
4064 /*
4065 * Update the last-error record both for failures and success, so we
4066 * can propagate the status code back to ring-3 for diagnostics.
4067 */
4068 hmR0VmxUpdateErrorRecord(pVCpu, rc);
4069 NOREF(pszVmcs);
4070 return rc;
4071}
4072
4073
4074/**
4075 * Does global VT-x initialization (called during module initialization).
4076 *
4077 * @returns VBox status code.
4078 */
4079VMMR0DECL(int) VMXR0GlobalInit(void)
4080{
4081#ifdef HMVMX_USE_FUNCTION_TABLE
4082 AssertCompile(VMX_EXIT_MAX + 1 == RT_ELEMENTS(g_apfnVMExitHandlers));
4083# ifdef VBOX_STRICT
4084 for (unsigned i = 0; i < RT_ELEMENTS(g_apfnVMExitHandlers); i++)
4085 Assert(g_apfnVMExitHandlers[i]);
4086# endif
4087#endif
4088 return VINF_SUCCESS;
4089}
4090
4091
4092/**
4093 * Does global VT-x termination (called during module termination).
4094 */
4095VMMR0DECL(void) VMXR0GlobalTerm()
4096{
4097 /* Nothing to do currently. */
4098}
4099
4100
4101/**
4102 * Sets up and activates VT-x on the current CPU.
4103 *
4104 * @returns VBox status code.
4105 * @param pHostCpu The HM physical-CPU structure.
4106 * @param pVM The cross context VM structure. Can be
4107 * NULL after a host resume operation.
4108 * @param pvCpuPage Pointer to the VMXON region (can be NULL if @a
4109 * fEnabledByHost is @c true).
4110 * @param HCPhysCpuPage Physical address of the VMXON region (can be 0 if
4111 * @a fEnabledByHost is @c true).
4112 * @param fEnabledByHost Set if SUPR0EnableVTx() or similar was used to
4113 * enable VT-x on the host.
4114 * @param pHwvirtMsrs Pointer to the hardware-virtualization MSRs.
4115 */
4116VMMR0DECL(int) VMXR0EnableCpu(PHMPHYSCPU pHostCpu, PVM pVM, void *pvCpuPage, RTHCPHYS HCPhysCpuPage, bool fEnabledByHost,
4117 PCSUPHWVIRTMSRS pHwvirtMsrs)
4118{
4119 AssertPtr(pHostCpu);
4120 AssertPtr(pHwvirtMsrs);
4121 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4122
4123 /* Enable VT-x if it's not already enabled by the host. */
4124 if (!fEnabledByHost)
4125 {
4126 int rc = hmR0VmxEnterRootMode(pVM, HCPhysCpuPage, pvCpuPage);
4127 if (RT_FAILURE(rc))
4128 return rc;
4129 }
4130
4131 /*
4132 * Flush all EPT tagged-TLB entries (in case VirtualBox or any other hypervisor have been
4133 * using EPTPs) so we don't retain any stale guest-physical mappings which won't get
4134 * invalidated when flushing by VPID.
4135 */
4136 if (pHwvirtMsrs->u.vmx.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_INVEPT_ALL_CONTEXTS)
4137 {
4138 hmR0VmxFlushEpt(NULL /* pVCpu */, NULL /* pVmcsInfo */, VMXTLBFLUSHEPT_ALL_CONTEXTS);
4139 pHostCpu->fFlushAsidBeforeUse = false;
4140 }
4141 else
4142 pHostCpu->fFlushAsidBeforeUse = true;
4143
4144 /* Ensure each VCPU scheduled on this CPU gets a new VPID on resume. See @bugref{6255}. */
4145 ++pHostCpu->cTlbFlushes;
4146
4147 return VINF_SUCCESS;
4148}
4149
4150
4151/**
4152 * Deactivates VT-x on the current CPU.
4153 *
4154 * @returns VBox status code.
4155 * @param pvCpuPage Pointer to the VMXON region.
4156 * @param HCPhysCpuPage Physical address of the VMXON region.
4157 *
4158 * @remarks This function should never be called when SUPR0EnableVTx() or
4159 * similar was used to enable VT-x on the host.
4160 */
4161VMMR0DECL(int) VMXR0DisableCpu(void *pvCpuPage, RTHCPHYS HCPhysCpuPage)
4162{
4163 RT_NOREF2(pvCpuPage, HCPhysCpuPage);
4164
4165 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4166 return hmR0VmxLeaveRootMode();
4167}
4168
4169
4170/**
4171 * Does per-VM VT-x initialization.
4172 *
4173 * @returns VBox status code.
4174 * @param pVM The cross context VM structure.
4175 */
4176VMMR0DECL(int) VMXR0InitVM(PVM pVM)
4177{
4178 AssertPtr(pVM);
4179 LogFlowFunc(("pVM=%p\n", pVM));
4180
4181 int rc = hmR0VmxStructsAlloc(pVM);
4182 if (RT_FAILURE(rc))
4183 {
4184 LogRelFunc(("Failed to allocated VMX structures. rc=%Rrc\n", rc));
4185 return rc;
4186 }
4187
4188 return VINF_SUCCESS;
4189}
4190
4191
4192/**
4193 * Does per-VM VT-x termination.
4194 *
4195 * @returns VBox status code.
4196 * @param pVM The cross context VM structure.
4197 */
4198VMMR0DECL(int) VMXR0TermVM(PVM pVM)
4199{
4200 AssertPtr(pVM);
4201 LogFlowFunc(("pVM=%p\n", pVM));
4202
4203#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4204 if (pVM->hm.s.vmx.hMemObjScratch != NIL_RTR0MEMOBJ)
4205 {
4206 Assert(pVM->hm.s.vmx.pvScratch);
4207 ASMMemZero32(pVM->hm.s.vmx.pvScratch, X86_PAGE_4K_SIZE);
4208 }
4209#endif
4210 hmR0VmxStructsFree(pVM);
4211 return VINF_SUCCESS;
4212}
4213
4214
4215/**
4216 * Sets up the VM for execution using hardware-assisted VMX.
4217 * This function is only called once per-VM during initialization.
4218 *
4219 * @returns VBox status code.
4220 * @param pVM The cross context VM structure.
4221 */
4222VMMR0DECL(int) VMXR0SetupVM(PVM pVM)
4223{
4224 AssertPtr(pVM);
4225 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
4226
4227 LogFlowFunc(("pVM=%p\n", pVM));
4228
4229 /*
4230 * At least verify if VMX is enabled, since we can't check if we're in
4231 * VMX root mode or not without causing a #GP.
4232 */
4233 RTCCUINTREG const uHostCr4 = ASMGetCR4();
4234 if (RT_LIKELY(uHostCr4 & X86_CR4_VMXE))
4235 { /* likely */ }
4236 else
4237 return VERR_VMX_NOT_IN_VMX_ROOT_MODE;
4238
4239 /*
4240 * Without unrestricted guest execution, pRealModeTSS and pNonPagingModeEPTPageTable *must*
4241 * always be allocated. We no longer support the highly unlikely case of unrestricted guest
4242 * without pRealModeTSS, see hmR3InitFinalizeR0Intel().
4243 */
4244 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
4245 && ( !pVM->hm.s.vmx.pNonPagingModeEPTPageTable
4246 || !pVM->hm.s.vmx.pRealModeTSS))
4247 {
4248 LogRelFunc(("Invalid real-on-v86 state.\n"));
4249 return VERR_INTERNAL_ERROR;
4250 }
4251
4252 /* Initialize these always, see hmR3InitFinalizeR0().*/
4253 pVM->hm.s.vmx.enmTlbFlushEpt = VMXTLBFLUSHEPT_NONE;
4254 pVM->hm.s.vmx.enmTlbFlushVpid = VMXTLBFLUSHVPID_NONE;
4255
4256 /* Setup the tagged-TLB flush handlers. */
4257 int rc = hmR0VmxSetupTaggedTlb(pVM);
4258 if (RT_FAILURE(rc))
4259 {
4260 LogRelFunc(("Failed to setup tagged TLB. rc=%Rrc\n", rc));
4261 return rc;
4262 }
4263
4264#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4265 /* Setup the shadow VMCS fields array and VMREAD/VMWRITE bitmaps. */
4266 if (pVM->hm.s.vmx.fUseVmcsShadowing)
4267 {
4268 rc = hmR0VmxSetupShadowVmcsFieldsArrays(pVM);
4269 if (RT_SUCCESS(rc))
4270 hmR0VmxSetupVmreadVmwriteBitmaps(pVM);
4271 else
4272 {
4273 LogRelFunc(("Failed to setup shadow VMCS fields arrays. rc=%Rrc\n", rc));
4274 return rc;
4275 }
4276 }
4277#endif
4278
4279 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++)
4280 {
4281 PVMCPU pVCpu = &pVM->aCpus[idCpu];
4282 Log4Func(("pVCpu=%p idCpu=%RU32\n", pVCpu, pVCpu->idCpu));
4283
4284 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfo, false /* fIsNstGstVmcs */);
4285 if (RT_SUCCESS(rc))
4286 {
4287#if HC_ARCH_BITS == 32
4288 hmR0VmxInitVmcsReadCache(pVCpu);
4289#endif
4290#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
4291 if (pVM->cpum.ro.GuestFeatures.fVmx)
4292 {
4293 rc = hmR0VmxSetupVmcs(pVCpu, &pVCpu->hm.s.vmx.VmcsInfoNstGst, true /* fIsNstGstVmcs */);
4294 if (RT_SUCCESS(rc))
4295 { /* likely */ }
4296 else
4297 {
4298 LogRelFunc(("Nested-guest VMCS setup failed. rc=%Rrc\n", rc));
4299 return rc;
4300 }
4301 }
4302#endif
4303 }
4304 else
4305 {
4306 LogRelFunc(("VMCS setup failed. rc=%Rrc\n", rc));
4307 return rc;
4308 }
4309 }
4310
4311 return VINF_SUCCESS;
4312}
4313
4314
4315#if HC_ARCH_BITS == 32
4316# ifdef VBOX_ENABLE_64_BITS_GUESTS
4317/**
4318 * Check if guest state allows safe use of 32-bit switcher again.
4319 *
4320 * Segment bases and protected mode structures must be 32-bit addressable
4321 * because the 32-bit switcher will ignore high dword when writing these VMCS
4322 * fields. See @bugref{8432} for details.
4323 *
4324 * @returns true if safe, false if must continue to use the 64-bit switcher.
4325 * @param pCtx Pointer to the guest-CPU context.
4326 *
4327 * @remarks No-long-jump zone!!!
4328 */
4329static bool hmR0VmxIs32BitSwitcherSafe(PCCPUMCTX pCtx)
4330{
4331 if (pCtx->gdtr.pGdt & UINT64_C(0xffffffff00000000)) return false;
4332 if (pCtx->idtr.pIdt & UINT64_C(0xffffffff00000000)) return false;
4333 if (pCtx->ldtr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4334 if (pCtx->tr.u64Base & UINT64_C(0xffffffff00000000)) return false;
4335 if (pCtx->es.u64Base & UINT64_C(0xffffffff00000000)) return false;
4336 if (pCtx->cs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4337 if (pCtx->ss.u64Base & UINT64_C(0xffffffff00000000)) return false;
4338 if (pCtx->ds.u64Base & UINT64_C(0xffffffff00000000)) return false;
4339 if (pCtx->fs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4340 if (pCtx->gs.u64Base & UINT64_C(0xffffffff00000000)) return false;
4341
4342 /* All good, bases are 32-bit. */
4343 return true;
4344}
4345# endif /* VBOX_ENABLE_64_BITS_GUESTS */
4346
4347# ifdef VBOX_STRICT
4348static bool hmR0VmxIsValidWriteFieldInCache(uint32_t idxField)
4349{
4350 switch (idxField)
4351 {
4352 case VMX_VMCS_GUEST_RIP:
4353 case VMX_VMCS_GUEST_RSP:
4354 case VMX_VMCS_GUEST_SYSENTER_EIP:
4355 case VMX_VMCS_GUEST_SYSENTER_ESP:
4356 case VMX_VMCS_GUEST_GDTR_BASE:
4357 case VMX_VMCS_GUEST_IDTR_BASE:
4358 case VMX_VMCS_GUEST_CS_BASE:
4359 case VMX_VMCS_GUEST_DS_BASE:
4360 case VMX_VMCS_GUEST_ES_BASE:
4361 case VMX_VMCS_GUEST_FS_BASE:
4362 case VMX_VMCS_GUEST_GS_BASE:
4363 case VMX_VMCS_GUEST_SS_BASE:
4364 case VMX_VMCS_GUEST_LDTR_BASE:
4365 case VMX_VMCS_GUEST_TR_BASE:
4366 case VMX_VMCS_GUEST_CR3:
4367 return true;
4368 }
4369 return false;
4370}
4371
4372static bool hmR0VmxIsValidReadFieldInCache(uint32_t idxField)
4373{
4374 switch (idxField)
4375 {
4376 /* Read-only fields. */
4377 case VMX_VMCS_RO_EXIT_QUALIFICATION:
4378 return true;
4379 }
4380 /* Remaining readable fields should also be writable. */
4381 return hmR0VmxIsValidWriteFieldInCache(idxField);
4382}
4383# endif /* VBOX_STRICT */
4384
4385
4386/**
4387 * Executes the specified handler in 64-bit mode.
4388 *
4389 * @returns VBox status code (no informational status codes).
4390 * @param pVCpu The cross context virtual CPU structure.
4391 * @param enmOp The operation to perform.
4392 * @param cParams Number of parameters.
4393 * @param paParam Array of 32-bit parameters.
4394 */
4395VMMR0DECL(int) VMXR0Execute64BitsHandler(PVMCPU pVCpu, HM64ON32OP enmOp, uint32_t cParams, uint32_t *paParam)
4396{
4397 AssertPtr(pVCpu);
4398 PVM pVM = pVCpu->CTX_SUFF(pVM);
4399 AssertReturn(pVM->hm.s.pfnHost32ToGuest64R0, VERR_HM_NO_32_TO_64_SWITCHER);
4400 Assert(enmOp > HM64ON32OP_INVALID && enmOp < HM64ON32OP_END);
4401 Assert(pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Write.aField));
4402 Assert(pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries <= RT_ELEMENTS(pVCpu->hm.s.vmx.VmcsCache.Read.aField));
4403
4404#ifdef VBOX_STRICT
4405 for (uint32_t i = 0; i < pVCpu->hm.s.vmx.VmcsCache.Write.cValidEntries; i++)
4406 Assert(hmR0VmxIsValidWriteFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Write.aField[i]));
4407
4408 for (uint32_t i = 0; i <pVCpu->hm.s.vmx.VmcsCache.Read.cValidEntries; i++)
4409 Assert(hmR0VmxIsValidReadFieldInCache(pVCpu->hm.s.vmx.VmcsCache.Read.aField[i]));
4410#endif
4411
4412 /* Disable interrupts. */
4413 RTCCUINTREG fOldEFlags = ASMIntDisableFlags();
4414
4415#ifdef VBOX_WITH_VMMR0_DISABLE_LAPIC_NMI
4416 RTCPUID idHostCpu = RTMpCpuId();
4417 CPUMR0SetLApic(pVCpu, idHostCpu);
4418#endif
4419
4420 /** @todo replace with hmR0VmxEnterRootMode() and hmR0VmxLeaveRootMode(). */
4421
4422 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4423 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4424
4425 /* Clear VMCS. Marking it inactive, clearing implementation-specific data and writing VMCS data back to memory. */
4426 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4427 hmR0VmxClearVmcs(pVmcsInfo);
4428
4429 /* Leave VMX root mode and disable VMX. */
4430 VMXDisable();
4431 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4432
4433 CPUMSetHyperESP(pVCpu, VMMGetStackRC(pVCpu));
4434 CPUMSetHyperEIP(pVCpu, enmOp);
4435 for (int i = (int)cParams - 1; i >= 0; i--)
4436 CPUMPushHyper(pVCpu, paParam[i]);
4437
4438 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatWorldSwitch3264, z);
4439
4440 /* Call the switcher. */
4441 int rc = pVM->hm.s.pfnHost32ToGuest64R0(pVM, RT_UOFFSETOF_DYN(VM, aCpus[pVCpu->idCpu].cpum) - RT_UOFFSETOF(VM, cpum));
4442 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatWorldSwitch3264, z);
4443
4444 /* Re-enable VMX to make sure the VMX instructions don't cause #UD faults. */
4445 SUPR0ChangeCR4(X86_CR4_VMXE, RTCCUINTREG_MAX);
4446
4447 /* Re-enter VMX root mode. */
4448 int rc2 = VMXEnable(HCPhysCpuPage);
4449 if (RT_FAILURE(rc2))
4450 {
4451 SUPR0ChangeCR4(0, ~X86_CR4_VMXE);
4452 ASMSetFlags(fOldEFlags);
4453 pVM->hm.s.vmx.HCPhysVmxEnableError = HCPhysCpuPage;
4454 return rc2;
4455 }
4456
4457 /* Restore the VMCS as the current VMCS. */
4458 rc2 = hmR0VmxLoadVmcs(pVmcsInfo);
4459 AssertRC(rc2);
4460 Assert(!(ASMGetFlags() & X86_EFL_IF));
4461 ASMSetFlags(fOldEFlags);
4462 return rc;
4463}
4464
4465
4466/**
4467 * Prepares for and executes VMLAUNCH (64-bit guests) for 32-bit hosts
4468 * supporting 64-bit guests.
4469 *
4470 * @returns VBox status code.
4471 * @param fResume Whether to VMLAUNCH or VMRESUME.
4472 * @param pCtx Pointer to the guest-CPU context.
4473 * @param pCache Pointer to the VMCS batch cache.
4474 * @param pVM The cross context VM structure.
4475 * @param pVCpu The cross context virtual CPU structure.
4476 */
4477DECLASM(int) VMXR0SwitcherStartVM64(RTHCUINT fResume, PCPUMCTX pCtx, PVMXVMCSCACHE pCache, PVM pVM, PVMCPU pVCpu)
4478{
4479 NOREF(fResume);
4480
4481 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
4482 PCHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
4483 RTHCPHYS const HCPhysCpuPage = pHostCpu->HCPhysMemObj;
4484
4485#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4486 pCache->uPos = 1;
4487 pCache->interPD = PGMGetInterPaeCR3(pVM);
4488 pCache->pSwitcher = (uint64_t)pVM->hm.s.pfnHost32ToGuest64R0;
4489#endif
4490
4491#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4492 pCache->TestIn.HCPhysCpuPage = 0;
4493 pCache->TestIn.HCPhysVmcs = 0;
4494 pCache->TestIn.pCache = 0;
4495 pCache->TestOut.HCPhysVmcs = 0;
4496 pCache->TestOut.pCache = 0;
4497 pCache->TestOut.pCtx = 0;
4498 pCache->TestOut.eflags = 0;
4499#else
4500 NOREF(pCache);
4501#endif
4502
4503 uint32_t aParam[10];
4504 aParam[0] = RT_LO_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Lo. */
4505 aParam[1] = RT_HI_U32(HCPhysCpuPage); /* Param 1: VMXON physical address - Hi. */
4506 aParam[2] = RT_LO_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Lo. */
4507 aParam[3] = RT_HI_U32(pVmcsInfo->HCPhysVmcs); /* Param 2: VMCS physical address - Hi. */
4508 aParam[4] = VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache);
4509 aParam[5] = 0;
4510 aParam[6] = VM_RC_ADDR(pVM, pVM);
4511 aParam[7] = 0;
4512 aParam[8] = VM_RC_ADDR(pVM, pVCpu);
4513 aParam[9] = 0;
4514
4515#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4516 pCtx->dr[4] = pVM->hm.s.vmx.pScratchPhys + 16 + 8;
4517 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 1;
4518#endif
4519 int rc = VMXR0Execute64BitsHandler(pVCpu, HM64ON32OP_VMXRCStartVM64, RT_ELEMENTS(aParam), &aParam[0]);
4520
4521#ifdef VBOX_WITH_CRASHDUMP_MAGIC
4522 Assert(*(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) == 5);
4523 Assert(pCtx->dr[4] == 10);
4524 *(uint32_t *)(pVM->hm.s.vmx.pScratch + 16 + 8) = 0xff;
4525#endif
4526
4527#if defined(DEBUG) && defined(VMX_USE_CACHED_VMCS_ACCESSES)
4528 AssertMsg(pCache->TestIn.HCPhysCpuPage == HCPhysCpuPage, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysCpuPage, HCPhysCpuPage));
4529 AssertMsg(pCache->TestIn.HCPhysVmcs == pVmcsInfo->HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4530 pVmcsInfo->HCPhysVmcs));
4531 AssertMsg(pCache->TestIn.HCPhysVmcs == pCache->TestOut.HCPhysVmcs, ("%RHp vs %RHp\n", pCache->TestIn.HCPhysVmcs,
4532 pCache->TestOut.HCPhysVmcs));
4533 AssertMsg(pCache->TestIn.pCache == pCache->TestOut.pCache, ("%RGv vs %RGv\n", pCache->TestIn.pCache,
4534 pCache->TestOut.pCache));
4535 AssertMsg(pCache->TestIn.pCache == VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache),
4536 ("%RGv vs %RGv\n", pCache->TestIn.pCache, VM_RC_ADDR(pVM, &pVM->aCpus[pVCpu->idCpu].hm.s.vmx.VmcsCache)));
4537 AssertMsg(pCache->TestIn.pCtx == pCache->TestOut.pCtx, ("%RGv vs %RGv\n", pCache->TestIn.pCtx,
4538 pCache->TestOut.pCtx));
4539 Assert(!(pCache->TestOut.eflags & X86_EFL_IF));
4540#endif
4541 NOREF(pCtx);
4542 return rc;
4543}
4544#endif
4545
4546
4547/**
4548 * Saves the host control registers (CR0, CR3, CR4) into the host-state area in
4549 * the VMCS.
4550 *
4551 * @returns VBox status code.
4552 */
4553static int hmR0VmxExportHostControlRegs(void)
4554{
4555 RTCCUINTREG uReg = ASMGetCR0();
4556 int rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR0, uReg);
4557 AssertRCReturn(rc, rc);
4558
4559 uReg = ASMGetCR3();
4560 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR3, uReg);
4561 AssertRCReturn(rc, rc);
4562
4563 uReg = ASMGetCR4();
4564 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_CR4, uReg);
4565 AssertRCReturn(rc, rc);
4566 return rc;
4567}
4568
4569
4570/**
4571 * Saves the host segment registers and GDTR, IDTR, (TR, GS and FS bases) into
4572 * the host-state area in the VMCS.
4573 *
4574 * @returns VBox status code.
4575 * @param pVCpu The cross context virtual CPU structure.
4576 */
4577static int hmR0VmxExportHostSegmentRegs(PVMCPU pVCpu)
4578{
4579#if HC_ARCH_BITS == 64
4580/**
4581 * Macro for adjusting host segment selectors to satisfy VT-x's VM-entry
4582 * requirements. See hmR0VmxExportHostSegmentRegs().
4583 */
4584# define VMXLOCAL_ADJUST_HOST_SEG(seg, selValue) \
4585 if ((selValue) & (X86_SEL_RPL | X86_SEL_LDT)) \
4586 { \
4587 bool fValidSelector = true; \
4588 if ((selValue) & X86_SEL_LDT) \
4589 { \
4590 uint32_t uAttr = ASMGetSegAttr((selValue)); \
4591 fValidSelector = RT_BOOL(uAttr != UINT32_MAX && (uAttr & X86_DESC_P)); \
4592 } \
4593 if (fValidSelector) \
4594 { \
4595 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_##seg; \
4596 pVCpu->hm.s.vmx.RestoreHost.uHostSel##seg = (selValue); \
4597 } \
4598 (selValue) = 0; \
4599 }
4600
4601 /*
4602 * If we've executed guest code using hardware-assisted VMX, the host-state bits
4603 * will be messed up. We should -not- save the messed up state without restoring
4604 * the original host-state, see @bugref{7240}.
4605 *
4606 * This apparently can happen (most likely the FPU changes), deal with it rather than
4607 * asserting. Was observed booting Solaris 10u10 32-bit guest.
4608 */
4609 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
4610 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
4611 {
4612 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags,
4613 pVCpu->idCpu));
4614 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
4615 }
4616 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
4617#else
4618 RT_NOREF(pVCpu);
4619#endif
4620
4621 /*
4622 * Host DS, ES, FS and GS segment registers.
4623 */
4624#if HC_ARCH_BITS == 64
4625 RTSEL uSelDS = ASMGetDS();
4626 RTSEL uSelES = ASMGetES();
4627 RTSEL uSelFS = ASMGetFS();
4628 RTSEL uSelGS = ASMGetGS();
4629#else
4630 RTSEL uSelDS = 0;
4631 RTSEL uSelES = 0;
4632 RTSEL uSelFS = 0;
4633 RTSEL uSelGS = 0;
4634#endif
4635
4636 /*
4637 * Host CS and SS segment registers.
4638 */
4639 RTSEL uSelCS = ASMGetCS();
4640 RTSEL uSelSS = ASMGetSS();
4641
4642 /*
4643 * Host TR segment register.
4644 */
4645 RTSEL uSelTR = ASMGetTR();
4646
4647#if HC_ARCH_BITS == 64
4648 /*
4649 * Determine if the host segment registers are suitable for VT-x. Otherwise use zero to
4650 * gain VM-entry and restore them before we get preempted.
4651 *
4652 * See Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers".
4653 */
4654 VMXLOCAL_ADJUST_HOST_SEG(DS, uSelDS);
4655 VMXLOCAL_ADJUST_HOST_SEG(ES, uSelES);
4656 VMXLOCAL_ADJUST_HOST_SEG(FS, uSelFS);
4657 VMXLOCAL_ADJUST_HOST_SEG(GS, uSelGS);
4658# undef VMXLOCAL_ADJUST_HOST_SEG
4659#endif
4660
4661 /* Verification based on Intel spec. 26.2.3 "Checks on Host Segment and Descriptor-Table Registers" */
4662 Assert(!(uSelCS & X86_SEL_RPL)); Assert(!(uSelCS & X86_SEL_LDT));
4663 Assert(!(uSelSS & X86_SEL_RPL)); Assert(!(uSelSS & X86_SEL_LDT));
4664 Assert(!(uSelDS & X86_SEL_RPL)); Assert(!(uSelDS & X86_SEL_LDT));
4665 Assert(!(uSelES & X86_SEL_RPL)); Assert(!(uSelES & X86_SEL_LDT));
4666 Assert(!(uSelFS & X86_SEL_RPL)); Assert(!(uSelFS & X86_SEL_LDT));
4667 Assert(!(uSelGS & X86_SEL_RPL)); Assert(!(uSelGS & X86_SEL_LDT));
4668 Assert(!(uSelTR & X86_SEL_RPL)); Assert(!(uSelTR & X86_SEL_LDT));
4669 Assert(uSelCS);
4670 Assert(uSelTR);
4671
4672 /* Write these host selector fields into the host-state area in the VMCS. */
4673 int rc = VMXWriteVmcs32(VMX_VMCS16_HOST_CS_SEL, uSelCS);
4674 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_SS_SEL, uSelSS);
4675#if HC_ARCH_BITS == 64
4676 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_DS_SEL, uSelDS);
4677 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_ES_SEL, uSelES);
4678 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_FS_SEL, uSelFS);
4679 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_GS_SEL, uSelGS);
4680#else
4681 NOREF(uSelDS);
4682 NOREF(uSelES);
4683 NOREF(uSelFS);
4684 NOREF(uSelGS);
4685#endif
4686 rc |= VMXWriteVmcs32(VMX_VMCS16_HOST_TR_SEL, uSelTR);
4687 AssertRCReturn(rc, rc);
4688
4689 /*
4690 * Host GDTR and IDTR.
4691 */
4692 RTGDTR Gdtr;
4693 RTIDTR Idtr;
4694 RT_ZERO(Gdtr);
4695 RT_ZERO(Idtr);
4696 ASMGetGDTR(&Gdtr);
4697 ASMGetIDTR(&Idtr);
4698 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, Gdtr.pGdt);
4699 rc |= VMXWriteVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, Idtr.pIdt);
4700 AssertRCReturn(rc, rc);
4701
4702#if HC_ARCH_BITS == 64
4703 /*
4704 * Determine if we need to manually need to restore the GDTR and IDTR limits as VT-x zaps
4705 * them to the maximum limit (0xffff) on every VM-exit.
4706 */
4707 if (Gdtr.cbGdt != 0xffff)
4708 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDTR;
4709
4710 /*
4711 * IDT limit is effectively capped at 0xfff. (See Intel spec. 6.14.1 "64-Bit Mode IDT" and
4712 * Intel spec. 6.2 "Exception and Interrupt Vectors".) Therefore if the host has the limit
4713 * as 0xfff, VT-x bloating the limit to 0xffff shouldn't cause any different CPU behavior.
4714 * However, several hosts either insists on 0xfff being the limit (Windows Patch Guard) or
4715 * uses the limit for other purposes (darwin puts the CPU ID in there but botches sidt
4716 * alignment in at least one consumer). So, we're only allowing the IDTR.LIMIT to be left
4717 * at 0xffff on hosts where we are sure it won't cause trouble.
4718 */
4719# if defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS)
4720 if (Idtr.cbIdt < 0x0fff)
4721# else
4722 if (Idtr.cbIdt != 0xffff)
4723# endif
4724 {
4725 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_IDTR;
4726 AssertCompile(sizeof(Idtr) == sizeof(X86XDTR64));
4727 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostIdtr, &Idtr, sizeof(X86XDTR64));
4728 }
4729#endif
4730
4731 /*
4732 * Host TR base. Verify that TR selector doesn't point past the GDT. Masking off the TI
4733 * and RPL bits is effectively what the CPU does for "scaling by 8". TI is always 0 and
4734 * RPL should be too in most cases.
4735 */
4736 AssertMsgReturn((uSelTR | X86_SEL_RPL_LDT) <= Gdtr.cbGdt,
4737 ("TR selector exceeds limit. TR=%RTsel cbGdt=%#x\n", uSelTR, Gdtr.cbGdt), VERR_VMX_INVALID_HOST_STATE);
4738
4739 PCX86DESCHC pDesc = (PCX86DESCHC)(Gdtr.pGdt + (uSelTR & X86_SEL_MASK));
4740#if HC_ARCH_BITS == 64
4741 uintptr_t const uTRBase = X86DESC64_BASE(pDesc);
4742
4743 /*
4744 * VT-x unconditionally restores the TR limit to 0x67 and type to 11 (32-bit busy TSS) on
4745 * all VM-exits. The type is the same for 64-bit busy TSS[1]. The limit needs manual
4746 * restoration if the host has something else. Task switching is not supported in 64-bit
4747 * mode[2], but the limit still matters as IOPM is supported in 64-bit mode. Restoring the
4748 * limit lazily while returning to ring-3 is safe because IOPM is not applicable in ring-0.
4749 *
4750 * [1] See Intel spec. 3.5 "System Descriptor Types".
4751 * [2] See Intel spec. 7.2.3 "TSS Descriptor in 64-bit mode".
4752 */
4753 PVM pVM = pVCpu->CTX_SUFF(pVM);
4754 Assert(pDesc->System.u4Type == 11);
4755 if ( pDesc->System.u16LimitLow != 0x67
4756 || pDesc->System.u4LimitHigh)
4757 {
4758 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_SEL_TR;
4759 /* If the host has made GDT read-only, we would need to temporarily toggle CR0.WP before writing the GDT. */
4760 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_READ_ONLY)
4761 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_READ_ONLY;
4762 pVCpu->hm.s.vmx.RestoreHost.uHostSelTR = uSelTR;
4763 }
4764
4765 /*
4766 * Store the GDTR as we need it when restoring the GDT and while restoring the TR.
4767 */
4768 if (pVCpu->hm.s.vmx.fRestoreHostFlags & (VMX_RESTORE_HOST_GDTR | VMX_RESTORE_HOST_SEL_TR))
4769 {
4770 AssertCompile(sizeof(Gdtr) == sizeof(X86XDTR64));
4771 memcpy(&pVCpu->hm.s.vmx.RestoreHost.HostGdtr, &Gdtr, sizeof(X86XDTR64));
4772 if (pVM->hm.s.fHostKernelFeatures & SUPKERNELFEATURES_GDT_NEED_WRITABLE)
4773 {
4774 /* The GDT is read-only but the writable GDT is available. */
4775 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_GDT_NEED_WRITABLE;
4776 pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.cb = Gdtr.cbGdt;
4777 rc = SUPR0GetCurrentGdtRw(&pVCpu->hm.s.vmx.RestoreHost.HostGdtrRw.uAddr);
4778 AssertRCReturn(rc, rc);
4779 }
4780 }
4781#else
4782 uintptr_t const uTRBase = X86DESC_BASE(pDesc);
4783#endif
4784 rc = VMXWriteVmcsHstN(VMX_VMCS_HOST_TR_BASE, uTRBase);
4785 AssertRCReturn(rc, rc);
4786
4787 /*
4788 * Host FS base and GS base.
4789 */
4790#if HC_ARCH_BITS == 64
4791 uint64_t const u64FSBase = ASMRdMsr(MSR_K8_FS_BASE);
4792 uint64_t const u64GSBase = ASMRdMsr(MSR_K8_GS_BASE);
4793 rc = VMXWriteVmcs64(VMX_VMCS_HOST_FS_BASE, u64FSBase);
4794 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_GS_BASE, u64GSBase);
4795 AssertRCReturn(rc, rc);
4796
4797 /* Store the base if we have to restore FS or GS manually as we need to restore the base as well. */
4798 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_FS)
4799 pVCpu->hm.s.vmx.RestoreHost.uHostFSBase = u64FSBase;
4800 if (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_SEL_GS)
4801 pVCpu->hm.s.vmx.RestoreHost.uHostGSBase = u64GSBase;
4802#endif
4803 return VINF_SUCCESS;
4804}
4805
4806
4807/**
4808 * Exports certain host MSRs in the VM-exit MSR-load area and some in the
4809 * host-state area of the VMCS.
4810 *
4811 * These MSRs will be automatically restored on the host after every successful
4812 * VM-exit.
4813 *
4814 * @returns VBox status code.
4815 * @param pVCpu The cross context virtual CPU structure.
4816 *
4817 * @remarks No-long-jump zone!!!
4818 */
4819static int hmR0VmxExportHostMsrs(PVMCPU pVCpu)
4820{
4821 AssertPtr(pVCpu);
4822
4823 /*
4824 * Save MSRs that we restore lazily (due to preemption or transition to ring-3)
4825 * rather than swapping them on every VM-entry.
4826 */
4827 hmR0VmxLazySaveHostMsrs(pVCpu);
4828
4829 /*
4830 * Host Sysenter MSRs.
4831 */
4832 int rc = VMXWriteVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, ASMRdMsr_Low(MSR_IA32_SYSENTER_CS));
4833#if HC_ARCH_BITS == 32
4834 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr_Low(MSR_IA32_SYSENTER_ESP));
4835 rc |= VMXWriteVmcs32(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr_Low(MSR_IA32_SYSENTER_EIP));
4836#else
4837 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, ASMRdMsr(MSR_IA32_SYSENTER_ESP));
4838 rc |= VMXWriteVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, ASMRdMsr(MSR_IA32_SYSENTER_EIP));
4839#endif
4840 AssertRCReturn(rc, rc);
4841
4842 /*
4843 * Host EFER MSR.
4844 *
4845 * If the CPU supports the newer VMCS controls for managing EFER, use it. Otherwise it's
4846 * done as part of auto-load/store MSR area in the VMCS, see hmR0VmxExportGuestMsrs().
4847 */
4848 PVM pVM = pVCpu->CTX_SUFF(pVM);
4849 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
4850 {
4851 rc = VMXWriteVmcs64(VMX_VMCS64_HOST_EFER_FULL, pVM->hm.s.vmx.u64HostMsrEfer);
4852 AssertRCReturn(rc, rc);
4853 }
4854
4855 /** @todo IA32_PERF_GLOBALCTRL, IA32_PAT also see
4856 * hmR0VmxExportGuestEntryExitCtls(). */
4857
4858 return VINF_SUCCESS;
4859}
4860
4861
4862/**
4863 * Figures out if we need to swap the EFER MSR which is particularly expensive.
4864 *
4865 * We check all relevant bits. For now, that's everything besides LMA/LME, as
4866 * these two bits are handled by VM-entry, see hmR0VMxExportGuestEntryExitCtls().
4867 *
4868 * @returns true if we need to load guest EFER, false otherwise.
4869 * @param pVCpu The cross context virtual CPU structure.
4870 *
4871 * @remarks Requires EFER, CR4.
4872 * @remarks No-long-jump zone!!!
4873 */
4874static bool hmR0VmxShouldSwapEferMsr(PCVMCPU pVCpu)
4875{
4876#ifdef HMVMX_ALWAYS_SWAP_EFER
4877 RT_NOREF(pVCpu);
4878 return true;
4879#else
4880 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
4881#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
4882 /* For 32-bit hosts running 64-bit guests, we always swap EFER MSR in the world-switcher. Nothing to do here. */
4883 if (CPUMIsGuestInLongModeEx(pCtx))
4884 return false;
4885#endif
4886
4887 PVM pVM = pVCpu->CTX_SUFF(pVM);
4888 uint64_t const u64HostEfer = pVM->hm.s.vmx.u64HostMsrEfer;
4889 uint64_t const u64GuestEfer = pCtx->msrEFER;
4890
4891 /*
4892 * For 64-bit guests, if EFER.SCE bit differs, we need to swap the EFER MSR
4893 * to ensure that the guest's SYSCALL behaviour isn't broken, see @bugref{7386}.
4894 */
4895 if ( CPUMIsGuestInLongModeEx(pCtx)
4896 && (u64GuestEfer & MSR_K6_EFER_SCE) != (u64HostEfer & MSR_K6_EFER_SCE))
4897 return true;
4898
4899 /*
4900 * If the guest uses PAE and EFER.NXE bit differs, we need to swap the EFER MSR
4901 * as it affects guest paging. 64-bit paging implies CR4.PAE as well.
4902 *
4903 * See Intel spec. 4.5 "IA-32e Paging".
4904 * See Intel spec. 4.1.1 "Three Paging Modes".
4905 *
4906 * Verify that we always intercept CR4.PAE and CR0.PG bits, so we don't need to
4907 * import CR4 and CR0 from the VMCS here as those bits are always up to date.
4908 */
4909 Assert(hmR0VmxGetFixedCr4Mask(pVCpu) & X86_CR4_PAE);
4910 Assert(hmR0VmxGetFixedCr0Mask(pVCpu) & X86_CR0_PG);
4911 if ( (pCtx->cr4 & X86_CR4_PAE)
4912 && (pCtx->cr0 & X86_CR0_PG)
4913 && (u64GuestEfer & MSR_K6_EFER_NXE) != (u64HostEfer & MSR_K6_EFER_NXE))
4914 {
4915 /* Assert that host is NX capable. */
4916 Assert(pVCpu->CTX_SUFF(pVM)->cpum.ro.HostFeatures.fNoExecute);
4917 return true;
4918 }
4919
4920 return false;
4921#endif
4922}
4923
4924/**
4925 * Exports the guest state with appropriate VM-entry and VM-exit controls in the
4926 * VMCS.
4927 *
4928 * This is typically required when the guest changes paging mode.
4929 *
4930 * @returns VBox status code.
4931 * @param pVCpu The cross context virtual CPU structure.
4932 * @param pVmxTransient The VMX-transient structure.
4933 *
4934 * @remarks Requires EFER.
4935 * @remarks No-long-jump zone!!!
4936 */
4937static int hmR0VmxExportGuestEntryExitCtls(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
4938{
4939 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS)
4940 {
4941 PVM pVM = pVCpu->CTX_SUFF(pVM);
4942 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
4943
4944 /*
4945 * VM-entry controls.
4946 */
4947 {
4948 uint32_t fVal = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
4949 uint32_t const fZap = pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
4950
4951 /*
4952 * Load the guest debug controls (DR7 and IA32_DEBUGCTL MSR) on VM-entry.
4953 * The first VT-x capable CPUs only supported the 1-setting of this bit.
4954 *
4955 * For nested-guests, this is a mandatory VM-entry control. It's also
4956 * required because we do not want to leak host bits to the nested-guest.
4957 */
4958 fVal |= VMX_ENTRY_CTLS_LOAD_DEBUG;
4959
4960 /*
4961 * Set if the guest is in long mode. This will set/clear the EFER.LMA bit on VM-entry.
4962 *
4963 * For nested-guests, the "IA-32e mode guest" control we initialize with what is
4964 * required to get the nested-guest working with hardware-assisted VMX execution.
4965 * It depends on the nested-guest's IA32_EFER.LMA bit. Remember, a guest hypervisor
4966 * can skip intercepting changes to the EFER MSR. This is why it it needs to be done
4967 * here rather than while merging the guest VMCS controls.
4968 */
4969 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
4970 fVal |= VMX_ENTRY_CTLS_IA32E_MODE_GUEST;
4971 else
4972 Assert(!(fVal & VMX_ENTRY_CTLS_IA32E_MODE_GUEST));
4973
4974 /*
4975 * If the CPU supports the newer VMCS controls for managing guest/host EFER, use it.
4976 *
4977 * For nested-guests, we use the "load IA32_EFER" if the hardware supports it,
4978 * regardless of whether the nested-guest VMCS specifies it because we are free to
4979 * load whatever MSRs we require and we do not need to modify the guest visible copy
4980 * of the VM-entry MSR load area.
4981 */
4982 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
4983 && hmR0VmxShouldSwapEferMsr(pVCpu))
4984 fVal |= VMX_ENTRY_CTLS_LOAD_EFER_MSR;
4985 else
4986 Assert(!(fVal & VMX_ENTRY_CTLS_LOAD_EFER_MSR));
4987
4988 /*
4989 * The following should -not- be set (since we're not in SMM mode):
4990 * - VMX_ENTRY_CTLS_ENTRY_TO_SMM
4991 * - VMX_ENTRY_CTLS_DEACTIVATE_DUAL_MON
4992 */
4993
4994 /** @todo VMX_ENTRY_CTLS_LOAD_PERF_MSR,
4995 * VMX_ENTRY_CTLS_LOAD_PAT_MSR. */
4996
4997 if ((fVal & fZap) == fVal)
4998 { /* likely */ }
4999 else
5000 {
5001 Log4Func(("Invalid VM-entry controls combo! Cpu=%#RX32 fVal=%#RX32 fZap=%#RX32\n",
5002 pVM->hm.s.vmx.Msrs.EntryCtls.n.allowed0, fVal, fZap));
5003 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_ENTRY;
5004 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5005 }
5006
5007 /* Commit it to the VMCS. */
5008 if (pVmcsInfo->u32EntryCtls != fVal)
5009 {
5010 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY, fVal);
5011 AssertRCReturn(rc, rc);
5012 pVmcsInfo->u32EntryCtls = fVal;
5013 }
5014 }
5015
5016 /*
5017 * VM-exit controls.
5018 */
5019 {
5020 uint32_t fVal = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0; /* Bits set here must be set in the VMCS. */
5021 uint32_t const fZap = pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1; /* Bits cleared here must be cleared in the VMCS. */
5022
5023 /*
5024 * Save debug controls (DR7 & IA32_DEBUGCTL_MSR). The first VT-x CPUs only
5025 * supported the 1-setting of this bit.
5026 *
5027 * For nested-guests, we set the "save debug controls" as the converse
5028 * "load debug controls" is mandatory for nested-guests anyway.
5029 */
5030 fVal |= VMX_EXIT_CTLS_SAVE_DEBUG;
5031
5032 /*
5033 * Set the host long mode active (EFER.LMA) bit (which Intel calls
5034 * "Host address-space size") if necessary. On VM-exit, VT-x sets both the
5035 * host EFER.LMA and EFER.LME bit to this value. See assertion in
5036 * hmR0VmxExportHostMsrs().
5037 *
5038 * For nested-guests, we always set this bit as we do not support 32-bit
5039 * hosts.
5040 */
5041#if HC_ARCH_BITS == 64
5042 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5043#else
5044 Assert(!pVmxTransient->fIsNestedGuest);
5045 Assert( pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64
5046 || pVmcsInfo->pfnStartVM == VMXR0StartVM32);
5047 /* Set the host address-space size based on the switcher, not guest state. See @bugref{8432}. */
5048 if (pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64)
5049 {
5050 /* The switcher returns to long mode, the EFER MSR is managed by the switcher. */
5051 fVal |= VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE;
5052 }
5053 else
5054 Assert(!(fVal & VMX_EXIT_CTLS_HOST_ADDR_SPACE_SIZE));
5055#endif
5056
5057 /*
5058 * If the VMCS EFER MSR fields are supported by the hardware, we use it.
5059 *
5060 * For nested-guests, we should use the "save IA32_EFER" control if we also
5061 * used the "load IA32_EFER" control while exporting VM-entry controls.
5062 */
5063 if ( pVM->hm.s.vmx.fSupportsVmcsEfer
5064 && hmR0VmxShouldSwapEferMsr(pVCpu))
5065 {
5066 fVal |= VMX_EXIT_CTLS_SAVE_EFER_MSR
5067 | VMX_EXIT_CTLS_LOAD_EFER_MSR;
5068 }
5069
5070 /*
5071 * Enable saving of the VMX-preemption timer value on VM-exit.
5072 * For nested-guests, currently not exposed/used.
5073 */
5074 if ( pVM->hm.s.vmx.fUsePreemptTimer
5075 && (pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed1 & VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER))
5076 fVal |= VMX_EXIT_CTLS_SAVE_PREEMPT_TIMER;
5077
5078 /* Don't acknowledge external interrupts on VM-exit. We want to let the host do that. */
5079 Assert(!(fVal & VMX_EXIT_CTLS_ACK_EXT_INT));
5080
5081 /** @todo VMX_EXIT_CTLS_LOAD_PERF_MSR,
5082 * VMX_EXIT_CTLS_SAVE_PAT_MSR,
5083 * VMX_EXIT_CTLS_LOAD_PAT_MSR. */
5084
5085 if ((fVal & fZap) == fVal)
5086 { /* likely */ }
5087 else
5088 {
5089 Log4Func(("Invalid VM-exit controls combo! cpu=%#RX32 fVal=%#RX32 fZap=%R#X32\n",
5090 pVM->hm.s.vmx.Msrs.ExitCtls.n.allowed0, fVal, fZap));
5091 pVCpu->hm.s.u32HMError = VMX_UFC_CTRL_EXIT;
5092 return VERR_HM_UNSUPPORTED_CPU_FEATURE_COMBO;
5093 }
5094
5095 /* Commit it to the VMCS. */
5096 if (pVmcsInfo->u32ExitCtls != fVal)
5097 {
5098 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_EXIT, fVal);
5099 AssertRCReturn(rc, rc);
5100 pVmcsInfo->u32ExitCtls = fVal;
5101 }
5102 }
5103
5104 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
5105 }
5106 return VINF_SUCCESS;
5107}
5108
5109
5110/**
5111 * Sets the TPR threshold in the VMCS.
5112 *
5113 * @returns VBox status code.
5114 * @param pVCpu The cross context virtual CPU structure.
5115 * @param pVmcsInfo The VMCS info. object.
5116 * @param u32TprThreshold The TPR threshold (task-priority class only).
5117 */
5118DECLINLINE(int) hmR0VmxApicSetTprThreshold(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint32_t u32TprThreshold)
5119{
5120 Assert(!(u32TprThreshold & ~VMX_TPR_THRESHOLD_MASK)); /* Bits 31:4 MBZ. */
5121 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
5122 RT_NOREF2(pVCpu, pVmcsInfo);
5123 return VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
5124}
5125
5126
5127/**
5128 * Exports the guest APIC TPR state into the VMCS.
5129 *
5130 * @returns VBox status code.
5131 * @param pVCpu The cross context virtual CPU structure.
5132 * @param pVmxTransient The VMX-transient structure.
5133 *
5134 * @remarks No-long-jump zone!!!
5135 */
5136static int hmR0VmxExportGuestApicTpr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5137{
5138 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_APIC_TPR)
5139 {
5140 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_APIC_TPR);
5141
5142 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5143 if (!pVmxTransient->fIsNestedGuest)
5144 {
5145 if ( PDMHasApic(pVCpu->CTX_SUFF(pVM))
5146 && APICIsEnabled(pVCpu))
5147 {
5148 /*
5149 * Setup TPR shadowing.
5150 */
5151 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
5152 {
5153 bool fPendingIntr = false;
5154 uint8_t u8Tpr = 0;
5155 uint8_t u8PendingIntr = 0;
5156 int rc = APICGetTpr(pVCpu, &u8Tpr, &fPendingIntr, &u8PendingIntr);
5157 AssertRCReturn(rc, rc);
5158
5159 /*
5160 * If there are interrupts pending but masked by the TPR, instruct VT-x to
5161 * cause a TPR-below-threshold VM-exit when the guest lowers its TPR below the
5162 * priority of the pending interrupt so we can deliver the interrupt. If there
5163 * are no interrupts pending, set threshold to 0 to not cause any
5164 * TPR-below-threshold VM-exits.
5165 */
5166 Assert(pVmcsInfo->pbVirtApic);
5167 pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR] = u8Tpr;
5168 uint32_t u32TprThreshold = 0;
5169 if (fPendingIntr)
5170 {
5171 /* Bits 3:0 of the TPR threshold field correspond to bits 7:4 of the TPR
5172 (which is the Task-Priority Class). */
5173 const uint8_t u8PendingPriority = u8PendingIntr >> 4;
5174 const uint8_t u8TprPriority = u8Tpr >> 4;
5175 if (u8PendingPriority <= u8TprPriority)
5176 u32TprThreshold = u8PendingPriority;
5177 }
5178
5179 rc = hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u32TprThreshold);
5180 AssertRCReturn(rc, rc);
5181 }
5182 }
5183 }
5184 /* else: the TPR threshold has already been updated while merging the nested-guest VMCS. */
5185 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_APIC_TPR);
5186 }
5187 return VINF_SUCCESS;
5188}
5189
5190
5191/**
5192 * Gets the guest interruptibility-state.
5193 *
5194 * @returns Guest's interruptibility-state.
5195 * @param pVCpu The cross context virtual CPU structure.
5196 * @param pVmxTransient The VMX-transient structure.
5197 *
5198 * @remarks No-long-jump zone!!!
5199 */
5200static uint32_t hmR0VmxGetGuestIntrState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5201{
5202 /*
5203 * Check if we should inhibit interrupt delivery due to instructions like STI and MOV SS.
5204 */
5205 uint32_t fIntrState = 0;
5206 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5207 {
5208 /* If inhibition is active, RIP and RFLAGS should've been updated
5209 (i.e. read previously from the VMCS or from ring-3). */
5210 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5211#ifdef VBOX_STRICT
5212 uint64_t const fExtrn = ASMAtomicUoReadU64(&pCtx->fExtrn);
5213 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
5214 AssertMsg(!(fExtrn & (CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS)), ("%#x\n", fExtrn));
5215#endif
5216 if (pCtx->rip == EMGetInhibitInterruptsPC(pVCpu))
5217 {
5218 if (pCtx->eflags.Bits.u1IF)
5219 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
5220 else
5221 fIntrState = VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS;
5222 }
5223 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
5224 {
5225 /*
5226 * We can clear the inhibit force flag as even if we go back to the recompiler
5227 * without executing guest code in VT-x, the flag's condition to be cleared is
5228 * met and thus the cleared state is correct.
5229 */
5230 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
5231 }
5232 }
5233
5234 /*
5235 * NMIs to the guest are blocked after an NMI is injected until the guest executes an IRET. We only
5236 * bother with virtual-NMI blocking when we have support for virtual NMIs in the CPU, otherwise
5237 * setting this would block host-NMIs and IRET will not clear the blocking.
5238 *
5239 * We always set NMI-exiting so when the host receives an NMI we get a VM-exit.
5240 *
5241 * See Intel spec. 26.6.1 "Interruptibility state". See @bugref{7445}.
5242 */
5243 if ( hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI)
5244 && CPUMIsGuestNmiBlocking(pVCpu))
5245 fIntrState |= VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI;
5246
5247 return fIntrState;
5248}
5249
5250
5251/**
5252 * Exports the exception intercepts required for guest execution in the VMCS.
5253 *
5254 * @returns VBox status code.
5255 * @param pVCpu The cross context virtual CPU structure.
5256 * @param pVmxTransient The VMX-transient structure.
5257 *
5258 * @remarks No-long-jump zone!!!
5259 */
5260static int hmR0VmxExportGuestXcptIntercepts(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5261{
5262 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_XCPT_INTERCEPTS)
5263 {
5264 /* When executing a nested-guest, we do not need to trap GIM hypercalls by intercepting #UD. */
5265 if ( !pVmxTransient->fIsNestedGuest
5266 && pVCpu->hm.s.fGIMTrapXcptUD)
5267 hmR0VmxAddXcptIntercept(pVmxTransient, X86_XCPT_UD);
5268 else
5269 hmR0VmxRemoveXcptIntercept(pVCpu, pVmxTransient, X86_XCPT_UD);
5270
5271 /* Other exception intercepts are handled elsewhere, e.g. while exporting guest CR0. */
5272 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_XCPT_INTERCEPTS);
5273 }
5274 return VINF_SUCCESS;
5275}
5276
5277
5278/**
5279 * Exports the guest's RIP into the guest-state area in the VMCS.
5280 *
5281 * @returns VBox status code.
5282 * @param pVCpu The cross context virtual CPU structure.
5283 *
5284 * @remarks No-long-jump zone!!!
5285 */
5286static int hmR0VmxExportGuestRip(PVMCPU pVCpu)
5287{
5288 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RIP)
5289 {
5290 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP);
5291
5292 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RIP, pVCpu->cpum.GstCtx.rip);
5293 AssertRCReturn(rc, rc);
5294
5295 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RIP);
5296 Log4Func(("rip=%#RX64\n", pVCpu->cpum.GstCtx.rip));
5297 }
5298 return VINF_SUCCESS;
5299}
5300
5301
5302/**
5303 * Exports the guest's RSP into the guest-state area in the VMCS.
5304 *
5305 * @returns VBox status code.
5306 * @param pVCpu The cross context virtual CPU structure.
5307 *
5308 * @remarks No-long-jump zone!!!
5309 */
5310static int hmR0VmxExportGuestRsp(PVMCPU pVCpu)
5311{
5312 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RSP)
5313 {
5314 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RSP);
5315
5316 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_RSP, pVCpu->cpum.GstCtx.rsp);
5317 AssertRCReturn(rc, rc);
5318
5319 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RSP);
5320 }
5321 return VINF_SUCCESS;
5322}
5323
5324
5325/**
5326 * Exports the guest's RFLAGS into the guest-state area in the VMCS.
5327 *
5328 * @returns VBox status code.
5329 * @param pVCpu The cross context virtual CPU structure.
5330 * @param pVmxTransient The VMX-transient structure.
5331 *
5332 * @remarks No-long-jump zone!!!
5333 */
5334static int hmR0VmxExportGuestRflags(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5335{
5336 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_RFLAGS)
5337 {
5338 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS);
5339
5340 /* Intel spec. 2.3.1 "System Flags and Fields in IA-32e Mode" claims the upper 32-bits of RFLAGS are reserved (MBZ).
5341 Let us assert it as such and use 32-bit VMWRITE. */
5342 Assert(!RT_HI_U32(pVCpu->cpum.GstCtx.rflags.u64));
5343 X86EFLAGS fEFlags = pVCpu->cpum.GstCtx.eflags;
5344 Assert(fEFlags.u32 & X86_EFL_RA1_MASK);
5345 Assert(!(fEFlags.u32 & ~(X86_EFL_1 | X86_EFL_LIVE_MASK)));
5346
5347 /*
5348 * If we're emulating real-mode using Virtual 8086 mode, save the real-mode eflags so
5349 * we can restore them on VM-exit. Modify the real-mode guest's eflags so that VT-x
5350 * can run the real-mode guest code under Virtual 8086 mode.
5351 */
5352 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5353 if (pVmcsInfo->RealMode.fRealOnV86Active)
5354 {
5355 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
5356 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
5357 Assert(!pVmxTransient->fIsNestedGuest);
5358 pVmcsInfo->RealMode.Eflags.u32 = fEFlags.u32; /* Save the original eflags of the real-mode guest. */
5359 fEFlags.Bits.u1VM = 1; /* Set the Virtual 8086 mode bit. */
5360 fEFlags.Bits.u2IOPL = 0; /* Change IOPL to 0, otherwise certain instructions won't fault. */
5361 }
5362
5363 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_RFLAGS, fEFlags.u32);
5364 AssertRCReturn(rc, rc);
5365
5366 /*
5367 * Setup pending debug exceptions if the guest is single-stepping using EFLAGS.TF.
5368 *
5369 * We must avoid setting any automatic debug exceptions delivery when single-stepping
5370 * through the hypervisor debugger using EFLAGS.TF.
5371 */
5372 if ( !pVmxTransient->fIsNestedGuest
5373 && !pVCpu->hm.s.fSingleInstruction
5374 && fEFlags.Bits.u1TF)
5375 {
5376 /** @todo r=ramshankar: Warning!! We ASSUME EFLAGS.TF will not cleared on
5377 * premature trips to ring-3 esp since IEM does not yet handle it. */
5378 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, VMX_VMCS_GUEST_PENDING_DEBUG_XCPT_BS);
5379 AssertRCReturn(rc, rc);
5380 }
5381 /** @todo NSTVMX: Handling copying of VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS from
5382 * nested-guest VMCS. */
5383
5384 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_RFLAGS);
5385 Log4Func(("eflags=%#RX32\n", fEFlags.u32));
5386 }
5387 return VINF_SUCCESS;
5388}
5389
5390
5391#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5392/**
5393 * Copies the nested-guest VMCS to the shadow VMCS.
5394 *
5395 * @returns VBox status code.
5396 * @param pVCpu The cross context virtual CPU structure.
5397 * @param pVmcsInfo The VMCS info. object.
5398 *
5399 * @remarks No-long-jump zone!!!
5400 */
5401static int hmR0VmxCopyNstGstToShadowVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5402{
5403 PVM pVM = pVCpu->CTX_SUFF(pVM);
5404 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5405
5406 /*
5407 * Disable interrupts so we don't get preempted while the shadow VMCS is the
5408 * current VMCS, as we may try saving guest lazy MSRs.
5409 *
5410 * Strictly speaking the lazy MSRs are not in the VMCS, but I'd rather not risk
5411 * calling the import VMCS code which is currently performing the guest MSR reads
5412 * (on 64-bit hosts) and accessing the auto-load/store MSR area on 32-bit hosts
5413 * and the rest of the VMX leave session machinery.
5414 */
5415 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
5416
5417 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5418 if (RT_SUCCESS(rc))
5419 {
5420 /*
5421 * Copy all guest read/write VMCS fields.
5422 *
5423 * We don't check for VMWRITE failures here for performance reasons and
5424 * because they are not expected to fail, barring irrecoverable conditions
5425 * like hardware errors.
5426 */
5427 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5428 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5429 {
5430 uint64_t u64Val;
5431 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5432 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5433 VMXWriteVmcs64(uVmcsField, u64Val);
5434 }
5435
5436 /*
5437 * If the host CPU supports writing all VMCS fields, copy the guest read-only
5438 * VMCS fields, so the guest can VMREAD them without causing a VM-exit.
5439 */
5440 if (pVM->hm.s.vmx.Msrs.u64Misc & VMX_MISC_VMWRITE_ALL)
5441 {
5442 uint32_t const cShadowVmcsRoFields = pVM->hm.s.vmx.cShadowVmcsRoFields;
5443 for (uint32_t i = 0; i < cShadowVmcsRoFields; i++)
5444 {
5445 uint64_t u64Val;
5446 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsRoFields[i];
5447 IEMReadVmxVmcsField(pVmcsNstGst, uVmcsField, &u64Val);
5448 VMXWriteVmcs64(uVmcsField, u64Val);
5449 }
5450 }
5451
5452 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5453 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5454 }
5455
5456 ASMSetFlags(fEFlags);
5457 return rc;
5458}
5459
5460
5461/**
5462 * Copies the shadow VMCS to the nested-guest VMCS.
5463 *
5464 * @returns VBox status code.
5465 * @param pVCpu The cross context virtual CPU structure.
5466 * @param pVmcsInfo The VMCS info. object.
5467 *
5468 * @remarks Called with interrupts disabled.
5469 */
5470static int hmR0VmxCopyShadowToNstGstVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5471{
5472 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
5473 PVM pVM = pVCpu->CTX_SUFF(pVM);
5474 PVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
5475
5476 int rc = hmR0VmxLoadShadowVmcs(pVmcsInfo);
5477 if (RT_SUCCESS(rc))
5478 {
5479 /*
5480 * Copy guest read/write fields from the shadow VMCS.
5481 * Guest read-only fields cannot be modified, so no need to copy them.
5482 *
5483 * We don't check for VMREAD failures here for performance reasons and
5484 * because they are not expected to fail, barring irrecoverable conditions
5485 * like hardware errors.
5486 */
5487 uint32_t const cShadowVmcsFields = pVM->hm.s.vmx.cShadowVmcsFields;
5488 for (uint32_t i = 0; i < cShadowVmcsFields; i++)
5489 {
5490 uint64_t u64Val;
5491 uint32_t const uVmcsField = pVM->hm.s.vmx.paShadowVmcsFields[i];
5492 VMXReadVmcs64(uVmcsField, &u64Val);
5493 IEMWriteVmxVmcsField(pVmcsNstGst, uVmcsField, u64Val);
5494 }
5495
5496 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
5497 rc |= hmR0VmxLoadVmcs(pVmcsInfo);
5498 }
5499 return rc;
5500}
5501
5502
5503/**
5504 * Enables VMCS shadowing for the given VMCS info. object.
5505 *
5506 * @param pVCpu The cross context virtual CPU structure.
5507 * @param pVmcsInfo The VMCS info. object.
5508 *
5509 * @remarks No-long-jump zone!!!
5510 */
5511static void hmR0VmxEnableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5512{
5513 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5514
5515 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5516 if (!(uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING))
5517 {
5518 Assert(pVmcsInfo->HCPhysShadowVmcs != 0 && pVmcsInfo->HCPhysShadowVmcs != NIL_RTHCPHYS);
5519 uProcCtls2 |= VMX_PROC_CTLS2_VMCS_SHADOWING;
5520 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5521 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, pVmcsInfo->HCPhysShadowVmcs);
5522 AssertRC(rc);
5523
5524 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5525 pVmcsInfo->u64VmcsLinkPtr = pVmcsInfo->HCPhysShadowVmcs;
5526 Log4Func(("Enabled\n"));
5527 }
5528}
5529
5530
5531/**
5532 * Disables VMCS shadowing for the given VMCS info. object.
5533 *
5534 * @param pVCpu The cross context virtual CPU structure.
5535 * @param pVmcsInfo The VMCS info. object.
5536 *
5537 * @remarks No-long-jump zone!!!
5538 */
5539static void hmR0VmxDisableVmcsShadowing(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
5540{
5541 NOREF(pVCpu); /* Used implicitly by VMXWriteVmcs64 on 32-bit hosts. */
5542
5543 /*
5544 * We want all VMREAD and VMWRITE instructions to cause VM-exits, so we clear the
5545 * VMCS shadowing control. However, VM-entry requires the shadow VMCS indicator bit
5546 * to match the VMCS shadowing control if the VMCS link pointer is not NIL_RTHCPHYS.
5547 * Hence, we must also reset the VMCS link pointer to ensure VM-entry does not fail.
5548 *
5549 * See Intel spec. 26.2.1.1 "VM-Execution Control Fields".
5550 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
5551 */
5552 uint32_t uProcCtls2 = pVmcsInfo->u32ProcCtls2;
5553 if (uProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
5554 {
5555 uProcCtls2 &= ~VMX_PROC_CTLS2_VMCS_SHADOWING;
5556 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, uProcCtls2);
5557 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, NIL_RTHCPHYS);
5558 AssertRC(rc);
5559
5560 pVmcsInfo->u32ProcCtls2 = uProcCtls2;
5561 pVmcsInfo->u64VmcsLinkPtr = NIL_RTHCPHYS;
5562 Log4Func(("Disabled\n"));
5563 }
5564}
5565#endif
5566
5567
5568/**
5569 * Exports the guest hardware-virtualization state.
5570 *
5571 * @returns VBox status code.
5572 * @param pVCpu The cross context virtual CPU structure.
5573 * @param pVmxTransient The VMX-transient structure.
5574 *
5575 * @remarks No-long-jump zone!!!
5576 */
5577static int hmR0VmxExportGuestHwvirtState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5578{
5579 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_HWVIRT)
5580 {
5581#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
5582 /*
5583 * Check if the VMX feature is exposed to the guest and if the host CPU supports
5584 * VMCS shadowing.
5585 */
5586 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUseVmcsShadowing)
5587 {
5588 /*
5589 * If the guest hypervisor has loaded a current VMCS and is in VMX root mode,
5590 * copy the guest hypervisor's current VMCS into the shadow VMCS and enable
5591 * VMCS shadowing to skip intercepting some or all VMREAD/VMWRITE VM-exits.
5592 *
5593 * We check for VMX root mode here in case the guest executes VMXOFF without
5594 * clearing the current VMCS pointer and our VMXOFF instruction emulation does
5595 * not clear the current VMCS pointer.
5596 */
5597 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5598 if ( CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx)
5599 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx)
5600 && CPUMIsGuestVmxCurrentVmcsValid(pVCpu, &pVCpu->cpum.GstCtx))
5601 {
5602 /* Paranoia. */
5603 Assert(!pVmxTransient->fIsNestedGuest);
5604
5605 /*
5606 * For performance reasons, also check if the guest hypervisor's current VMCS
5607 * was newly loaded or modified before copying it to the shadow VMCS.
5608 */
5609 if (!pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs)
5610 {
5611 int rc = hmR0VmxCopyNstGstToShadowVmcs(pVCpu, pVmcsInfo);
5612 AssertRCReturn(rc, rc);
5613 pVCpu->hm.s.vmx.fCopiedNstGstToShadowVmcs = true;
5614 }
5615 hmR0VmxEnableVmcsShadowing(pVCpu, pVmcsInfo);
5616 }
5617 else
5618 hmR0VmxDisableVmcsShadowing(pVCpu, pVmcsInfo);
5619 }
5620#else
5621 NOREF(pVmxTransient);
5622#endif
5623 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_HWVIRT);
5624 }
5625 return VINF_SUCCESS;
5626}
5627
5628
5629/**
5630 * Exports the guest CR0 control register into the guest-state area in the VMCS.
5631 *
5632 * The guest FPU state is always pre-loaded hence we don't need to bother about
5633 * sharing FPU related CR0 bits between the guest and host.
5634 *
5635 * @returns VBox status code.
5636 * @param pVCpu The cross context virtual CPU structure.
5637 * @param pVmxTransient The VMX-transient structure.
5638 *
5639 * @remarks No-long-jump zone!!!
5640 */
5641static int hmR0VmxExportGuestCR0(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5642{
5643 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR0)
5644 {
5645 PVM pVM = pVCpu->CTX_SUFF(pVM);
5646 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5647
5648 /*
5649 * Figure out fixed CR0 bits in VMX operation.
5650 */
5651 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5652 uint64_t fSetCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5653 uint64_t const fZapCr0 = pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1;
5654 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5655 fSetCr0 &= ~(uint64_t)(X86_CR0_PE | X86_CR0_PG);
5656 else
5657 Assert((fSetCr0 & (X86_CR0_PE | X86_CR0_PG)) == (X86_CR0_PE | X86_CR0_PG));
5658
5659 if (!pVmxTransient->fIsNestedGuest)
5660 {
5661 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5662 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5663 uint64_t const u64ShadowCr0 = u64GuestCr0;
5664 Assert(!RT_HI_U32(u64GuestCr0));
5665
5666 /*
5667 * Setup VT-x's view of the guest CR0.
5668 */
5669 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
5670 if (pVM->hm.s.fNestedPaging)
5671 {
5672 if (CPUMIsGuestPagingEnabled(pVCpu))
5673 {
5674 /* The guest has paging enabled, let it access CR3 without causing a VM-exit if supported. */
5675 uProcCtls &= ~( VMX_PROC_CTLS_CR3_LOAD_EXIT
5676 | VMX_PROC_CTLS_CR3_STORE_EXIT);
5677 }
5678 else
5679 {
5680 /* The guest doesn't have paging enabled, make CR3 access cause a VM-exit to update our shadow. */
5681 uProcCtls |= VMX_PROC_CTLS_CR3_LOAD_EXIT
5682 | VMX_PROC_CTLS_CR3_STORE_EXIT;
5683 }
5684
5685 /* If we have unrestricted guest execution, we never have to intercept CR3 reads. */
5686 if (pVM->hm.s.vmx.fUnrestrictedGuest)
5687 uProcCtls &= ~VMX_PROC_CTLS_CR3_STORE_EXIT;
5688 }
5689 else
5690 {
5691 /* Guest CPL 0 writes to its read-only pages should cause a #PF VM-exit. */
5692 u64GuestCr0 |= X86_CR0_WP;
5693 }
5694
5695 /*
5696 * Guest FPU bits.
5697 *
5698 * Since we pre-load the guest FPU always before VM-entry there is no need to track lazy state
5699 * using CR0.TS.
5700 *
5701 * Intel spec. 23.8 "Restrictions on VMX operation" mentions that CR0.NE bit must always be
5702 * set on the first CPUs to support VT-x and no mention of with regards to UX in VM-entry checks.
5703 */
5704 u64GuestCr0 |= X86_CR0_NE;
5705
5706 /* If CR0.NE isn't set, we need to intercept #MF exceptions and report them to the guest differently. */
5707 bool const fInterceptMF = !(u64ShadowCr0 & X86_CR0_NE);
5708
5709 /*
5710 * Update exception intercepts.
5711 */
5712 uint32_t uXcptBitmap = pVmcsInfo->u32XcptBitmap;
5713 if (pVmcsInfo->RealMode.fRealOnV86Active)
5714 {
5715 Assert(PDMVmmDevHeapIsEnabled(pVM));
5716 Assert(pVM->hm.s.vmx.pRealModeTSS);
5717 uXcptBitmap |= HMVMX_REAL_MODE_XCPT_MASK;
5718 }
5719 else
5720 {
5721 /* For now, cleared here as mode-switches can happen outside HM/VT-x. See @bugref{7626#c11}. */
5722 uXcptBitmap &= ~HMVMX_REAL_MODE_XCPT_MASK;
5723 if (fInterceptMF)
5724 uXcptBitmap |= RT_BIT(X86_XCPT_MF);
5725 }
5726
5727 /* Additional intercepts for debugging, define these yourself explicitly. */
5728#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
5729 uXcptBitmap |= 0
5730 | RT_BIT(X86_XCPT_BP)
5731 | RT_BIT(X86_XCPT_DE)
5732 | RT_BIT(X86_XCPT_NM)
5733 | RT_BIT(X86_XCPT_TS)
5734 | RT_BIT(X86_XCPT_UD)
5735 | RT_BIT(X86_XCPT_NP)
5736 | RT_BIT(X86_XCPT_SS)
5737 | RT_BIT(X86_XCPT_GP)
5738 | RT_BIT(X86_XCPT_PF)
5739 | RT_BIT(X86_XCPT_MF)
5740 ;
5741#elif defined(HMVMX_ALWAYS_TRAP_PF)
5742 uXcptBitmap |= RT_BIT(X86_XCPT_PF);
5743#endif
5744 if (pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv)
5745 uXcptBitmap |= RT_BIT(X86_XCPT_GP);
5746 Assert(pVM->hm.s.fNestedPaging || (uXcptBitmap & RT_BIT(X86_XCPT_PF)));
5747
5748 /* Apply the hardware specified fixed CR0 bits and enable caching. */
5749 u64GuestCr0 |= fSetCr0;
5750 u64GuestCr0 &= fZapCr0;
5751 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5752
5753 /* Commit the CR0 and related fields to the guest VMCS. */
5754 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0); /** @todo Fix to 64-bit when we drop 32-bit. */
5755 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5756 if (uProcCtls != pVmcsInfo->u32ProcCtls)
5757 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
5758 if (uXcptBitmap != pVmcsInfo->u32XcptBitmap)
5759 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, uXcptBitmap);
5760 AssertRCReturn(rc, rc);
5761
5762 /* Update our caches. */
5763 pVmcsInfo->u32ProcCtls = uProcCtls;
5764 pVmcsInfo->u32XcptBitmap = uXcptBitmap;
5765
5766 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5767 }
5768 else
5769 {
5770 /*
5771 * With nested-guests, we may have extended the guest/host mask here since we
5772 * merged in the outer guest's mask. Thus, the merged mask can include more bits
5773 * (to read from the nested-guest CR0 read-shadow) than the guest hypervisor
5774 * originally supplied. We must copy those bits from the nested-guest CR0 into
5775 * the nested-guest CR0 read-shadow.
5776 */
5777 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
5778 uint64_t u64GuestCr0 = pVCpu->cpum.GstCtx.cr0;
5779 uint64_t const u64ShadowCr0 = CPUMGetGuestVmxMaskedCr0(pVCpu, &pVCpu->cpum.GstCtx, pVmcsInfo->u64Cr0Mask);
5780 Assert(!RT_HI_U32(u64GuestCr0));
5781 Assert(u64GuestCr0 & X86_CR0_NE);
5782
5783 /*
5784 * Apply the hardware specified fixed CR0 bits and enable caching.
5785 * Note! We could be altering our VMX emulation's fixed bits. We thus
5786 * need to re-apply them while importing CR0.
5787 */
5788 u64GuestCr0 |= fSetCr0;
5789 u64GuestCr0 &= fZapCr0;
5790 u64GuestCr0 &= ~(uint64_t)(X86_CR0_CD | X86_CR0_NW);
5791
5792 /* Commit the CR0 and CR0 read-shadow to the nested-guest VMCS. */
5793 /** @todo NSTVMX: Fix to 64-bit when we drop 32-bit. */
5794 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR0, u64GuestCr0);
5795 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, u64ShadowCr0);
5796 AssertRCReturn(rc, rc);
5797
5798 Log4Func(("cr0=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64\n", u64GuestCr0, u64ShadowCr0, fSetCr0, fZapCr0));
5799 }
5800
5801 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR0);
5802 }
5803
5804 return VINF_SUCCESS;
5805}
5806
5807
5808/**
5809 * Exports the guest control registers (CR3, CR4) into the guest-state area
5810 * in the VMCS.
5811 *
5812 * @returns VBox strict status code.
5813 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
5814 * without unrestricted guest access and the VMMDev is not presently
5815 * mapped (e.g. EFI32).
5816 *
5817 * @param pVCpu The cross context virtual CPU structure.
5818 * @param pVmxTransient The VMX-transient structure.
5819 *
5820 * @remarks No-long-jump zone!!!
5821 */
5822static VBOXSTRICTRC hmR0VmxExportGuestCR3AndCR4(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
5823{
5824 int rc = VINF_SUCCESS;
5825 PVM pVM = pVCpu->CTX_SUFF(pVM);
5826
5827 /*
5828 * Guest CR2.
5829 * It's always loaded in the assembler code. Nothing to do here.
5830 */
5831
5832 /*
5833 * Guest CR3.
5834 */
5835 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR3)
5836 {
5837 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR3);
5838
5839 RTGCPHYS GCPhysGuestCr3 = NIL_RTGCPHYS;
5840 if (pVM->hm.s.fNestedPaging)
5841 {
5842 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5843 pVmcsInfo->HCPhysEPTP = PGMGetHyperCR3(pVCpu);
5844
5845 /* Validate. See Intel spec. 28.2.2 "EPT Translation Mechanism" and 24.6.11 "Extended-Page-Table Pointer (EPTP)" */
5846 Assert(pVmcsInfo->HCPhysEPTP != NIL_RTHCPHYS);
5847 Assert(!(pVmcsInfo->HCPhysEPTP & UINT64_C(0xfff0000000000000)));
5848 Assert(!(pVmcsInfo->HCPhysEPTP & 0xfff));
5849
5850 /* VMX_EPT_MEMTYPE_WB support is already checked in hmR0VmxSetupTaggedTlb(). */
5851 pVmcsInfo->HCPhysEPTP |= VMX_EPT_MEMTYPE_WB
5852 | (VMX_EPT_PAGE_WALK_LENGTH_DEFAULT << VMX_EPT_PAGE_WALK_LENGTH_SHIFT);
5853
5854 /* Validate. See Intel spec. 26.2.1 "Checks on VMX Controls" */
5855 AssertMsg( ((pVmcsInfo->HCPhysEPTP >> 3) & 0x07) == 3 /* Bits 3:5 (EPT page walk length - 1) must be 3. */
5856 && ((pVmcsInfo->HCPhysEPTP >> 7) & 0x1f) == 0, /* Bits 7:11 MBZ. */
5857 ("EPTP %#RX64\n", pVmcsInfo->HCPhysEPTP));
5858 AssertMsg( !((pVmcsInfo->HCPhysEPTP >> 6) & 0x01) /* Bit 6 (EPT accessed & dirty bit). */
5859 || (pVM->hm.s.vmx.Msrs.u64EptVpidCaps & MSR_IA32_VMX_EPT_VPID_CAP_EPT_ACCESS_DIRTY),
5860 ("EPTP accessed/dirty bit not supported by CPU but set %#RX64\n", pVmcsInfo->HCPhysEPTP));
5861
5862 rc = VMXWriteVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, pVmcsInfo->HCPhysEPTP);
5863 AssertRCReturn(rc, rc);
5864
5865 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5866 if ( pVM->hm.s.vmx.fUnrestrictedGuest
5867 || CPUMIsGuestPagingEnabledEx(pCtx))
5868 {
5869 /* If the guest is in PAE mode, pass the PDPEs to VT-x using the VMCS fields. */
5870 if (CPUMIsGuestInPAEModeEx(pCtx))
5871 {
5872 rc = PGMGstGetPaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
5873 AssertRCReturn(rc, rc);
5874 rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, pVCpu->hm.s.aPdpes[0].u);
5875 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, pVCpu->hm.s.aPdpes[1].u);
5876 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, pVCpu->hm.s.aPdpes[2].u);
5877 rc |= VMXWriteVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, pVCpu->hm.s.aPdpes[3].u);
5878 AssertRCReturn(rc, rc);
5879 }
5880
5881 /*
5882 * The guest's view of its CR3 is unblemished with nested paging when the
5883 * guest is using paging or we have unrestricted guest execution to handle
5884 * the guest when it's not using paging.
5885 */
5886 GCPhysGuestCr3 = pCtx->cr3;
5887 }
5888 else
5889 {
5890 /*
5891 * The guest is not using paging, but the CPU (VT-x) has to. While the guest
5892 * thinks it accesses physical memory directly, we use our identity-mapped
5893 * page table to map guest-linear to guest-physical addresses. EPT takes care
5894 * of translating it to host-physical addresses.
5895 */
5896 RTGCPHYS GCPhys;
5897 Assert(pVM->hm.s.vmx.pNonPagingModeEPTPageTable);
5898
5899 /* We obtain it here every time as the guest could have relocated this PCI region. */
5900 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pNonPagingModeEPTPageTable, &GCPhys);
5901 if (RT_SUCCESS(rc))
5902 { /* likely */ }
5903 else if (rc == VERR_PDM_DEV_HEAP_R3_TO_GCPHYS)
5904 {
5905 Log4Func(("VERR_PDM_DEV_HEAP_R3_TO_GCPHYS -> VINF_EM_RESCHEDULE_REM\n"));
5906 return VINF_EM_RESCHEDULE_REM; /* We cannot execute now, switch to REM/IEM till the guest maps in VMMDev. */
5907 }
5908 else
5909 AssertMsgFailedReturn(("%Rrc\n", rc), rc);
5910
5911 GCPhysGuestCr3 = GCPhys;
5912 }
5913
5914 Log4Func(("u32GuestCr3=%#RGp (GstN)\n", GCPhysGuestCr3));
5915 rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_CR3, GCPhysGuestCr3);
5916 AssertRCReturn(rc, rc);
5917 }
5918 else
5919 {
5920 /* Non-nested paging case, just use the hypervisor's CR3. */
5921 RTHCPHYS const HCPhysGuestCr3 = PGMGetHyperCR3(pVCpu);
5922
5923 Log4Func(("u32GuestCr3=%#RHv (HstN)\n", HCPhysGuestCr3));
5924 rc = VMXWriteVmcsHstN(VMX_VMCS_GUEST_CR3, HCPhysGuestCr3);
5925 AssertRCReturn(rc, rc);
5926 }
5927
5928 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR3);
5929 }
5930
5931 /*
5932 * Guest CR4.
5933 * ASSUMES this is done everytime we get in from ring-3! (XCR0)
5934 */
5935 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CR4)
5936 {
5937 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
5938 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
5939
5940 /*
5941 * Figure out fixed CR4 bits in VMX operation.
5942 */
5943 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
5944 uint64_t const fSetCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5945 uint64_t const fZapCr4 = pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1;
5946
5947 /*
5948 * With nested-guests, we may have extended the guest/host mask here (since we
5949 * merged in the outer guest's mask, see hmR0VmxMergeVmcsNested). This means, the
5950 * mask can include more bits (to read from the nested-guest CR4 read-shadow) than
5951 * the guest hypervisor originally supplied. Thus, we should, in essence, copy
5952 * those bits from the nested-guest CR4 into the nested-guest CR4 read-shadow.
5953 */
5954 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
5955 uint64_t u64GuestCr4 = pCtx->cr4;
5956 uint64_t const u64ShadowCr4 = !pVmxTransient->fIsNestedGuest
5957 ? pCtx->cr4
5958 : CPUMGetGuestVmxMaskedCr4(pVCpu, pCtx, pVmcsInfo->u64Cr4Mask);
5959 Assert(!RT_HI_U32(u64GuestCr4));
5960
5961 /*
5962 * Setup VT-x's view of the guest CR4.
5963 *
5964 * If we're emulating real-mode using virtual-8086 mode, we want to redirect software
5965 * interrupts to the 8086 program interrupt handler. Clear the VME bit (the interrupt
5966 * redirection bitmap is already all 0, see hmR3InitFinalizeR0())
5967 *
5968 * See Intel spec. 20.2 "Software Interrupt Handling Methods While in Virtual-8086 Mode".
5969 */
5970 if (pVmcsInfo->RealMode.fRealOnV86Active)
5971 {
5972 Assert(pVM->hm.s.vmx.pRealModeTSS);
5973 Assert(PDMVmmDevHeapIsEnabled(pVM));
5974 u64GuestCr4 &= ~(uint64_t)X86_CR4_VME;
5975 }
5976
5977 if (pVM->hm.s.fNestedPaging)
5978 {
5979 if ( !CPUMIsGuestPagingEnabledEx(pCtx)
5980 && !pVM->hm.s.vmx.fUnrestrictedGuest)
5981 {
5982 /* We use 4 MB pages in our identity mapping page table when the guest doesn't have paging. */
5983 u64GuestCr4 |= X86_CR4_PSE;
5984 /* Our identity mapping is a 32-bit page directory. */
5985 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
5986 }
5987 /* else use guest CR4.*/
5988 }
5989 else
5990 {
5991 Assert(!pVmxTransient->fIsNestedGuest);
5992
5993 /*
5994 * The shadow paging modes and guest paging modes are different, the shadow is in accordance with the host
5995 * paging mode and thus we need to adjust VT-x's view of CR4 depending on our shadow page tables.
5996 */
5997 switch (pVCpu->hm.s.enmShadowMode)
5998 {
5999 case PGMMODE_REAL: /* Real-mode. */
6000 case PGMMODE_PROTECTED: /* Protected mode without paging. */
6001 case PGMMODE_32_BIT: /* 32-bit paging. */
6002 {
6003 u64GuestCr4 &= ~(uint64_t)X86_CR4_PAE;
6004 break;
6005 }
6006
6007 case PGMMODE_PAE: /* PAE paging. */
6008 case PGMMODE_PAE_NX: /* PAE paging with NX. */
6009 {
6010 u64GuestCr4 |= X86_CR4_PAE;
6011 break;
6012 }
6013
6014 case PGMMODE_AMD64: /* 64-bit AMD paging (long mode). */
6015 case PGMMODE_AMD64_NX: /* 64-bit AMD paging (long mode) with NX enabled. */
6016#ifdef VBOX_ENABLE_64_BITS_GUESTS
6017 break;
6018#endif
6019 default:
6020 AssertFailed();
6021 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6022 }
6023 }
6024
6025 /*
6026 * Apply the hardware specified fixed CR4 bits (mainly CR4.VMXE).
6027 * Note! For nested-guests, we could be altering our VMX emulation's
6028 * fixed bits. We thus need to re-apply them while importing CR4.
6029 */
6030 u64GuestCr4 |= fSetCr4;
6031 u64GuestCr4 &= fZapCr4;
6032
6033 /* Commit the CR4 and CR4 read-shadow to the guest VMCS. */
6034 /** @todo Fix to 64-bit when we drop 32-bit. */
6035 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_CR4, u64GuestCr4);
6036 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, u64ShadowCr4);
6037 AssertRCReturn(rc, rc);
6038
6039 /* Whether to save/load/restore XCR0 during world switch depends on CR4.OSXSAVE and host+guest XCR0. */
6040 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
6041
6042 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CR4);
6043
6044 Log4Func(("cr4=%#RX64 shadow=%#RX64 set=%#RX64 zap=%#RX64)\n", u64GuestCr4, u64ShadowCr4, fSetCr4, fZapCr4));
6045 }
6046 return rc;
6047}
6048
6049
6050/**
6051 * Exports the guest debug registers into the guest-state area in the VMCS.
6052 * The guest debug bits are partially shared with the host (e.g. DR6, DR0-3).
6053 *
6054 * This also sets up whether \#DB and MOV DRx accesses cause VM-exits.
6055 *
6056 * @returns VBox status code.
6057 * @param pVCpu The cross context virtual CPU structure.
6058 * @param pVmxTransient The VMX-transient structure.
6059 *
6060 * @remarks No-long-jump zone!!!
6061 */
6062static int hmR0VmxExportSharedDebugState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6063{
6064 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
6065
6066 /** @todo NSTVMX: Figure out what we want to do with nested-guest instruction
6067 * stepping. */
6068 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6069 if (pVmxTransient->fIsNestedGuest)
6070 {
6071 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, CPUMGetGuestDR7(pVCpu));
6072 AssertRCReturn(rc, rc);
6073 return VINF_SUCCESS;
6074 }
6075
6076#ifdef VBOX_STRICT
6077 /* Validate. Intel spec. 26.3.1.1 "Checks on Guest Controls Registers, Debug Registers, MSRs" */
6078 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
6079 {
6080 /* Validate. Intel spec. 17.2 "Debug Registers", recompiler paranoia checks. */
6081 Assert((pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_MBZ_MASK | X86_DR7_RAZ_MASK)) == 0);
6082 Assert((pVCpu->cpum.GstCtx.dr[7] & X86_DR7_RA1_MASK) == X86_DR7_RA1_MASK);
6083 }
6084#endif
6085
6086 bool fSteppingDB = false;
6087 bool fInterceptMovDRx = false;
6088 uint32_t uProcCtls = pVmcsInfo->u32ProcCtls;
6089 if (pVCpu->hm.s.fSingleInstruction)
6090 {
6091 /* If the CPU supports the monitor trap flag, use it for single stepping in DBGF and avoid intercepting #DB. */
6092 PVM pVM = pVCpu->CTX_SUFF(pVM);
6093 if (pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_MONITOR_TRAP_FLAG)
6094 {
6095 uProcCtls |= VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
6096 Assert(fSteppingDB == false);
6097 }
6098 else
6099 {
6100 pVCpu->cpum.GstCtx.eflags.u32 |= X86_EFL_TF;
6101 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_RFLAGS;
6102 pVCpu->hm.s.fClearTrapFlag = true;
6103 fSteppingDB = true;
6104 }
6105 }
6106
6107 uint32_t u32GuestDr7;
6108 if ( fSteppingDB
6109 || (CPUMGetHyperDR7(pVCpu) & X86_DR7_ENABLED_MASK))
6110 {
6111 /*
6112 * Use the combined guest and host DRx values found in the hypervisor register set
6113 * because the hypervisor debugger has breakpoints active or someone is single stepping
6114 * on the host side without a monitor trap flag.
6115 *
6116 * Note! DBGF expects a clean DR6 state before executing guest code.
6117 */
6118#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6119 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6120 && !CPUMIsHyperDebugStateActivePending(pVCpu))
6121 {
6122 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6123 Assert(CPUMIsHyperDebugStateActivePending(pVCpu));
6124 Assert(!CPUMIsGuestDebugStateActivePending(pVCpu));
6125 }
6126 else
6127#endif
6128 if (!CPUMIsHyperDebugStateActive(pVCpu))
6129 {
6130 CPUMR0LoadHyperDebugState(pVCpu, true /* include DR6 */);
6131 Assert(CPUMIsHyperDebugStateActive(pVCpu));
6132 Assert(!CPUMIsGuestDebugStateActive(pVCpu));
6133 }
6134
6135 /* Update DR7 with the hypervisor value (other DRx registers are handled by CPUM one way or another). */
6136 u32GuestDr7 = (uint32_t)CPUMGetHyperDR7(pVCpu);
6137 pVCpu->hm.s.fUsingHyperDR7 = true;
6138 fInterceptMovDRx = true;
6139 }
6140 else
6141 {
6142 /*
6143 * If the guest has enabled debug registers, we need to load them prior to
6144 * executing guest code so they'll trigger at the right time.
6145 */
6146 if (pVCpu->cpum.GstCtx.dr[7] & (X86_DR7_ENABLED_MASK | X86_DR7_GD))
6147 {
6148#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6149 if ( CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
6150 && !CPUMIsGuestDebugStateActivePending(pVCpu))
6151 {
6152 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6153 Assert(CPUMIsGuestDebugStateActivePending(pVCpu));
6154 Assert(!CPUMIsHyperDebugStateActivePending(pVCpu));
6155 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6156 }
6157 else
6158#endif
6159 if (!CPUMIsGuestDebugStateActive(pVCpu))
6160 {
6161 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
6162 Assert(CPUMIsGuestDebugStateActive(pVCpu));
6163 Assert(!CPUMIsHyperDebugStateActive(pVCpu));
6164 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxArmed);
6165 }
6166 Assert(!fInterceptMovDRx);
6167 }
6168 /*
6169 * If no debugging enabled, we'll lazy load DR0-3. Unlike on AMD-V, we
6170 * must intercept #DB in order to maintain a correct DR6 guest value, and
6171 * because we need to intercept it to prevent nested #DBs from hanging the
6172 * CPU, we end up always having to intercept it. See hmR0VmxSetupVmcsXcptBitmap().
6173 */
6174#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
6175 else if ( !CPUMIsGuestDebugStateActivePending(pVCpu)
6176 && !CPUMIsGuestDebugStateActive(pVCpu))
6177#else
6178 else if (!CPUMIsGuestDebugStateActive(pVCpu))
6179#endif
6180 {
6181 fInterceptMovDRx = true;
6182 }
6183
6184 /* Update DR7 with the actual guest value. */
6185 u32GuestDr7 = pVCpu->cpum.GstCtx.dr[7];
6186 pVCpu->hm.s.fUsingHyperDR7 = false;
6187 }
6188
6189 if (fInterceptMovDRx)
6190 uProcCtls |= VMX_PROC_CTLS_MOV_DR_EXIT;
6191 else
6192 uProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
6193
6194 /*
6195 * Update the processor-based VM-execution controls with the MOV-DRx intercepts and the
6196 * monitor-trap flag and update our cache.
6197 */
6198 if (uProcCtls != pVmcsInfo->u32ProcCtls)
6199 {
6200 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, uProcCtls);
6201 AssertRCReturn(rc2, rc2);
6202 pVmcsInfo->u32ProcCtls = uProcCtls;
6203 }
6204
6205 /*
6206 * Update guest DR7.
6207 */
6208 int rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, u32GuestDr7);
6209 AssertRCReturn(rc, rc);
6210
6211 /*
6212 * If we have forced EFLAGS.TF to be set because we're single-stepping in the hypervisor debugger,
6213 * we need to clear interrupt inhibition if any as otherwise it causes a VM-entry failure.
6214 *
6215 * See Intel spec. 26.3.1.5 "Checks on Guest Non-Register State".
6216 */
6217 if (fSteppingDB)
6218 {
6219 Assert(pVCpu->hm.s.fSingleInstruction);
6220 Assert(pVCpu->cpum.GstCtx.eflags.Bits.u1TF);
6221
6222 uint32_t fIntrState = 0;
6223 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
6224 AssertRCReturn(rc, rc);
6225
6226 if (fIntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
6227 {
6228 fIntrState &= ~(VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
6229 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
6230 AssertRCReturn(rc, rc);
6231 }
6232 }
6233
6234 return VINF_SUCCESS;
6235}
6236
6237
6238#ifdef VBOX_STRICT
6239/**
6240 * Strict function to validate segment registers.
6241 *
6242 * @param pVCpu The cross context virtual CPU structure.
6243 * @param pVmcsInfo The VMCS info. object.
6244 *
6245 * @remarks Will import guest CR0 on strict builds during validation of
6246 * segments.
6247 */
6248static void hmR0VmxValidateSegmentRegs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
6249{
6250 /*
6251 * Validate segment registers. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
6252 *
6253 * The reason we check for attribute value 0 in this function and not just the unusable bit is
6254 * because hmR0VmxExportGuestSegReg() only updates the VMCS' copy of the value with the
6255 * unusable bit and doesn't change the guest-context value.
6256 */
6257 PVM pVM = pVCpu->CTX_SUFF(pVM);
6258 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6259 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR0);
6260 if ( !pVM->hm.s.vmx.fUnrestrictedGuest
6261 && ( !CPUMIsGuestInRealModeEx(pCtx)
6262 && !CPUMIsGuestInV86ModeEx(pCtx)))
6263 {
6264 /* Protected mode checks */
6265 /* CS */
6266 Assert(pCtx->cs.Attr.n.u1Present);
6267 Assert(!(pCtx->cs.Attr.u & 0xf00));
6268 Assert(!(pCtx->cs.Attr.u & 0xfffe0000));
6269 Assert( (pCtx->cs.u32Limit & 0xfff) == 0xfff
6270 || !(pCtx->cs.Attr.n.u1Granularity));
6271 Assert( !(pCtx->cs.u32Limit & 0xfff00000)
6272 || (pCtx->cs.Attr.n.u1Granularity));
6273 /* CS cannot be loaded with NULL in protected mode. */
6274 Assert(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE)); /** @todo is this really true even for 64-bit CS? */
6275 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
6276 Assert(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl);
6277 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
6278 Assert(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl);
6279 else
6280 AssertMsgFailed(("Invalid CS Type %#x\n", pCtx->cs.Attr.n.u2Dpl));
6281 /* SS */
6282 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6283 Assert(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL));
6284 if ( !(pCtx->cr0 & X86_CR0_PE)
6285 || pCtx->cs.Attr.n.u4Type == 3)
6286 {
6287 Assert(!pCtx->ss.Attr.n.u2Dpl);
6288 }
6289 if (pCtx->ss.Attr.u && !(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
6290 {
6291 Assert((pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL));
6292 Assert(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7);
6293 Assert(pCtx->ss.Attr.n.u1Present);
6294 Assert(!(pCtx->ss.Attr.u & 0xf00));
6295 Assert(!(pCtx->ss.Attr.u & 0xfffe0000));
6296 Assert( (pCtx->ss.u32Limit & 0xfff) == 0xfff
6297 || !(pCtx->ss.Attr.n.u1Granularity));
6298 Assert( !(pCtx->ss.u32Limit & 0xfff00000)
6299 || (pCtx->ss.Attr.n.u1Granularity));
6300 }
6301 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSegReg(). */
6302 if (pCtx->ds.Attr.u && !(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
6303 {
6304 Assert(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6305 Assert(pCtx->ds.Attr.n.u1Present);
6306 Assert(pCtx->ds.Attr.n.u4Type > 11 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL));
6307 Assert(!(pCtx->ds.Attr.u & 0xf00));
6308 Assert(!(pCtx->ds.Attr.u & 0xfffe0000));
6309 Assert( (pCtx->ds.u32Limit & 0xfff) == 0xfff
6310 || !(pCtx->ds.Attr.n.u1Granularity));
6311 Assert( !(pCtx->ds.u32Limit & 0xfff00000)
6312 || (pCtx->ds.Attr.n.u1Granularity));
6313 Assert( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6314 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ));
6315 }
6316 if (pCtx->es.Attr.u && !(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
6317 {
6318 Assert(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6319 Assert(pCtx->es.Attr.n.u1Present);
6320 Assert(pCtx->es.Attr.n.u4Type > 11 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL));
6321 Assert(!(pCtx->es.Attr.u & 0xf00));
6322 Assert(!(pCtx->es.Attr.u & 0xfffe0000));
6323 Assert( (pCtx->es.u32Limit & 0xfff) == 0xfff
6324 || !(pCtx->es.Attr.n.u1Granularity));
6325 Assert( !(pCtx->es.u32Limit & 0xfff00000)
6326 || (pCtx->es.Attr.n.u1Granularity));
6327 Assert( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6328 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ));
6329 }
6330 if (pCtx->fs.Attr.u && !(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
6331 {
6332 Assert(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6333 Assert(pCtx->fs.Attr.n.u1Present);
6334 Assert(pCtx->fs.Attr.n.u4Type > 11 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL));
6335 Assert(!(pCtx->fs.Attr.u & 0xf00));
6336 Assert(!(pCtx->fs.Attr.u & 0xfffe0000));
6337 Assert( (pCtx->fs.u32Limit & 0xfff) == 0xfff
6338 || !(pCtx->fs.Attr.n.u1Granularity));
6339 Assert( !(pCtx->fs.u32Limit & 0xfff00000)
6340 || (pCtx->fs.Attr.n.u1Granularity));
6341 Assert( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6342 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6343 }
6344 if (pCtx->gs.Attr.u && !(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
6345 {
6346 Assert(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED);
6347 Assert(pCtx->gs.Attr.n.u1Present);
6348 Assert(pCtx->gs.Attr.n.u4Type > 11 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL));
6349 Assert(!(pCtx->gs.Attr.u & 0xf00));
6350 Assert(!(pCtx->gs.Attr.u & 0xfffe0000));
6351 Assert( (pCtx->gs.u32Limit & 0xfff) == 0xfff
6352 || !(pCtx->gs.Attr.n.u1Granularity));
6353 Assert( !(pCtx->gs.u32Limit & 0xfff00000)
6354 || (pCtx->gs.Attr.n.u1Granularity));
6355 Assert( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
6356 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ));
6357 }
6358 /* 64-bit capable CPUs. */
6359# if HC_ARCH_BITS == 64
6360 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6361 Assert(!pCtx->ss.Attr.u || !RT_HI_U32(pCtx->ss.u64Base));
6362 Assert(!pCtx->ds.Attr.u || !RT_HI_U32(pCtx->ds.u64Base));
6363 Assert(!pCtx->es.Attr.u || !RT_HI_U32(pCtx->es.u64Base));
6364# endif
6365 }
6366 else if ( CPUMIsGuestInV86ModeEx(pCtx)
6367 || ( CPUMIsGuestInRealModeEx(pCtx)
6368 && !pVM->hm.s.vmx.fUnrestrictedGuest))
6369 {
6370 /* Real and v86 mode checks. */
6371 /* hmR0VmxExportGuestSegReg() writes the modified in VMCS. We want what we're feeding to VT-x. */
6372 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
6373 if (pVmcsInfo->RealMode.fRealOnV86Active)
6374 {
6375 u32CSAttr = 0xf3; u32SSAttr = 0xf3; u32DSAttr = 0xf3;
6376 u32ESAttr = 0xf3; u32FSAttr = 0xf3; u32GSAttr = 0xf3;
6377 }
6378 else
6379 {
6380 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u; u32DSAttr = pCtx->ds.Attr.u;
6381 u32ESAttr = pCtx->es.Attr.u; u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
6382 }
6383
6384 /* CS */
6385 AssertMsg((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), ("CS base %#x %#x\n", pCtx->cs.u64Base, pCtx->cs.Sel));
6386 Assert(pCtx->cs.u32Limit == 0xffff);
6387 Assert(u32CSAttr == 0xf3);
6388 /* SS */
6389 Assert(pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4);
6390 Assert(pCtx->ss.u32Limit == 0xffff);
6391 Assert(u32SSAttr == 0xf3);
6392 /* DS */
6393 Assert(pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4);
6394 Assert(pCtx->ds.u32Limit == 0xffff);
6395 Assert(u32DSAttr == 0xf3);
6396 /* ES */
6397 Assert(pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4);
6398 Assert(pCtx->es.u32Limit == 0xffff);
6399 Assert(u32ESAttr == 0xf3);
6400 /* FS */
6401 Assert(pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4);
6402 Assert(pCtx->fs.u32Limit == 0xffff);
6403 Assert(u32FSAttr == 0xf3);
6404 /* GS */
6405 Assert(pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4);
6406 Assert(pCtx->gs.u32Limit == 0xffff);
6407 Assert(u32GSAttr == 0xf3);
6408 /* 64-bit capable CPUs. */
6409# if HC_ARCH_BITS == 64
6410 Assert(!RT_HI_U32(pCtx->cs.u64Base));
6411 Assert(!u32SSAttr || !RT_HI_U32(pCtx->ss.u64Base));
6412 Assert(!u32DSAttr || !RT_HI_U32(pCtx->ds.u64Base));
6413 Assert(!u32ESAttr || !RT_HI_U32(pCtx->es.u64Base));
6414# endif
6415 }
6416}
6417#endif /* VBOX_STRICT */
6418
6419
6420/**
6421 * Exports a guest segment register into the guest-state area in the VMCS.
6422 *
6423 * @returns VBox status code.
6424 * @param pVCpu The cross context virtual CPU structure.
6425 * @param pVmcsInfo The VMCS info. object.
6426 * @param iSegReg The segment register number (X86_SREG_XXX).
6427 * @param pSelReg Pointer to the segment selector.
6428 *
6429 * @remarks No-long-jump zone!!!
6430 */
6431static int hmR0VmxExportGuestSegReg(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo, uint8_t iSegReg, PCCPUMSELREG pSelReg)
6432{
6433 Assert(iSegReg < X86_SREG_COUNT);
6434 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
6435 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
6436 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
6437 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
6438
6439 uint32_t u32Access = pSelReg->Attr.u;
6440 if (pVmcsInfo->RealMode.fRealOnV86Active)
6441 {
6442 /* VT-x requires our real-using-v86 mode hack to override the segment access-right bits. */
6443 u32Access = 0xf3;
6444 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.pRealModeTSS);
6445 Assert(PDMVmmDevHeapIsEnabled(pVCpu->CTX_SUFF(pVM)));
6446 RT_NOREF_PV(pVCpu);
6447 }
6448 else
6449 {
6450 /*
6451 * The way to differentiate between whether this is really a null selector or was just
6452 * a selector loaded with 0 in real-mode is using the segment attributes. A selector
6453 * loaded in real-mode with the value 0 is valid and usable in protected-mode and we
6454 * should -not- mark it as an unusable segment. Both the recompiler & VT-x ensures
6455 * NULL selectors loaded in protected-mode have their attribute as 0.
6456 */
6457 if (!u32Access)
6458 u32Access = X86DESCATTR_UNUSABLE;
6459 }
6460
6461 /* Validate segment access rights. Refer to Intel spec. "26.3.1.2 Checks on Guest Segment Registers". */
6462 AssertMsg((u32Access & X86DESCATTR_UNUSABLE) || (u32Access & X86_SEL_TYPE_ACCESSED),
6463 ("Access bit not set for usable segment. idx=%#x sel=%#x attr %#x\n", idxBase, pSelReg, pSelReg->Attr.u));
6464
6465 /*
6466 * Commit it to the VMCS.
6467 */
6468 int rc = VMXWriteVmcs32(idxSel, pSelReg->Sel);
6469 rc |= VMXWriteVmcs32(idxLimit, pSelReg->u32Limit);
6470 rc |= VMXWriteVmcsGstN(idxBase, pSelReg->u64Base);
6471 rc |= VMXWriteVmcs32(idxAttr, u32Access);
6472 AssertRCReturn(rc, rc);
6473 return rc;
6474}
6475
6476
6477/**
6478 * Exports the guest segment registers, GDTR, IDTR, LDTR, TR into the guest-state
6479 * area in the VMCS.
6480 *
6481 * @returns VBox status code.
6482 * @param pVCpu The cross context virtual CPU structure.
6483 * @param pVmxTransient The VMX-transient structure.
6484 *
6485 * @remarks Will import guest CR0 on strict builds during validation of
6486 * segments.
6487 * @remarks No-long-jump zone!!!
6488 */
6489static int hmR0VmxExportGuestSegRegsXdtr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6490{
6491 int rc = VERR_INTERNAL_ERROR_5;
6492 PVM pVM = pVCpu->CTX_SUFF(pVM);
6493 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6494 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6495
6496 /*
6497 * Guest Segment registers: CS, SS, DS, ES, FS, GS.
6498 */
6499 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SREG_MASK)
6500 {
6501#ifdef VBOX_WITH_REM
6502 if (!pVM->hm.s.vmx.fUnrestrictedGuest)
6503 {
6504 Assert(!pVmxTransient->fIsNestedGuest);
6505 Assert(pVM->hm.s.vmx.pRealModeTSS);
6506 AssertCompile(PGMMODE_REAL < PGMMODE_PROTECTED);
6507 if ( pVmcsInfo->fWasInRealMode
6508 && PGMGetGuestMode(pVCpu) >= PGMMODE_PROTECTED)
6509 {
6510 /*
6511 * Notify the recompiler must flush its code-cache as the guest -may-
6512 * rewrite code it in real-mode (e.g. OpenBSD 4.0).
6513 */
6514 REMFlushTBs(pVM);
6515 Log4Func(("Switch to protected mode detected!\n"));
6516 pVmcsInfo->fWasInRealMode = false;
6517 }
6518 }
6519#endif
6520 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_CS)
6521 {
6522 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CS);
6523 if (pVmcsInfo->RealMode.fRealOnV86Active)
6524 pVmcsInfo->RealMode.AttrCS.u = pCtx->cs.Attr.u;
6525 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_CS, &pCtx->cs);
6526 AssertRCReturn(rc, rc);
6527 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_CS);
6528 }
6529
6530 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SS)
6531 {
6532 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SS);
6533 if (pVmcsInfo->RealMode.fRealOnV86Active)
6534 pVmcsInfo->RealMode.AttrSS.u = pCtx->ss.Attr.u;
6535 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_SS, &pCtx->ss);
6536 AssertRCReturn(rc, rc);
6537 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SS);
6538 }
6539
6540 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_DS)
6541 {
6542 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_DS);
6543 if (pVmcsInfo->RealMode.fRealOnV86Active)
6544 pVmcsInfo->RealMode.AttrDS.u = pCtx->ds.Attr.u;
6545 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_DS, &pCtx->ds);
6546 AssertRCReturn(rc, rc);
6547 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_DS);
6548 }
6549
6550 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_ES)
6551 {
6552 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_ES);
6553 if (pVmcsInfo->RealMode.fRealOnV86Active)
6554 pVmcsInfo->RealMode.AttrES.u = pCtx->es.Attr.u;
6555 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_ES, &pCtx->es);
6556 AssertRCReturn(rc, rc);
6557 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_ES);
6558 }
6559
6560 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_FS)
6561 {
6562 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_FS);
6563 if (pVmcsInfo->RealMode.fRealOnV86Active)
6564 pVmcsInfo->RealMode.AttrFS.u = pCtx->fs.Attr.u;
6565 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_FS, &pCtx->fs);
6566 AssertRCReturn(rc, rc);
6567 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_FS);
6568 }
6569
6570 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GS)
6571 {
6572 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GS);
6573 if (pVmcsInfo->RealMode.fRealOnV86Active)
6574 pVmcsInfo->RealMode.AttrGS.u = pCtx->gs.Attr.u;
6575 rc = hmR0VmxExportGuestSegReg(pVCpu, pVmcsInfo, X86_SREG_GS, &pCtx->gs);
6576 AssertRCReturn(rc, rc);
6577 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GS);
6578 }
6579
6580#ifdef VBOX_STRICT
6581 hmR0VmxValidateSegmentRegs(pVCpu, pVmcsInfo);
6582#endif
6583 Log4Func(("cs={%#04x base=%#RX64 limit=%#RX32 attr=%#RX32}\n", pCtx->cs.Sel, pCtx->cs.u64Base, pCtx->cs.u32Limit,
6584 pCtx->cs.Attr.u));
6585 }
6586
6587 /*
6588 * Guest TR.
6589 */
6590 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_TR)
6591 {
6592 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_TR);
6593
6594 /*
6595 * Real-mode emulation using virtual-8086 mode with CR4.VME. Interrupt redirection is
6596 * achieved using the interrupt redirection bitmap (all bits cleared to let the guest
6597 * handle INT-n's) in the TSS. See hmR3InitFinalizeR0() to see how pRealModeTSS is setup.
6598 */
6599 uint16_t u16Sel;
6600 uint32_t u32Limit;
6601 uint64_t u64Base;
6602 uint32_t u32AccessRights;
6603 if (!pVmcsInfo->RealMode.fRealOnV86Active)
6604 {
6605 u16Sel = pCtx->tr.Sel;
6606 u32Limit = pCtx->tr.u32Limit;
6607 u64Base = pCtx->tr.u64Base;
6608 u32AccessRights = pCtx->tr.Attr.u;
6609 }
6610 else
6611 {
6612 Assert(!pVmxTransient->fIsNestedGuest);
6613 Assert(pVM->hm.s.vmx.pRealModeTSS);
6614 Assert(PDMVmmDevHeapIsEnabled(pVM)); /* Guaranteed by HMCanExecuteGuest() -XXX- what about inner loop changes? */
6615
6616 /* We obtain it here every time as PCI regions could be reconfigured in the guest, changing the VMMDev base. */
6617 RTGCPHYS GCPhys;
6618 rc = PDMVmmDevHeapR3ToGCPhys(pVM, pVM->hm.s.vmx.pRealModeTSS, &GCPhys);
6619 AssertRCReturn(rc, rc);
6620
6621 X86DESCATTR DescAttr;
6622 DescAttr.u = 0;
6623 DescAttr.n.u1Present = 1;
6624 DescAttr.n.u4Type = X86_SEL_TYPE_SYS_386_TSS_BUSY;
6625
6626 u16Sel = 0;
6627 u32Limit = HM_VTX_TSS_SIZE;
6628 u64Base = GCPhys;
6629 u32AccessRights = DescAttr.u;
6630 }
6631
6632 /* Validate. */
6633 Assert(!(u16Sel & RT_BIT(2)));
6634 AssertMsg( (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_386_TSS_BUSY
6635 || (u32AccessRights & 0xf) == X86_SEL_TYPE_SYS_286_TSS_BUSY, ("TSS is not busy!? %#x\n", u32AccessRights));
6636 AssertMsg(!(u32AccessRights & X86DESCATTR_UNUSABLE), ("TR unusable bit is not clear!? %#x\n", u32AccessRights));
6637 Assert(!(u32AccessRights & RT_BIT(4))); /* System MBZ.*/
6638 Assert(u32AccessRights & RT_BIT(7)); /* Present MB1.*/
6639 Assert(!(u32AccessRights & 0xf00)); /* 11:8 MBZ. */
6640 Assert(!(u32AccessRights & 0xfffe0000)); /* 31:17 MBZ. */
6641 Assert( (u32Limit & 0xfff) == 0xfff
6642 || !(u32AccessRights & RT_BIT(15))); /* Granularity MBZ. */
6643 Assert( !(pCtx->tr.u32Limit & 0xfff00000)
6644 || (u32AccessRights & RT_BIT(15))); /* Granularity MB1. */
6645
6646 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_TR_SEL, u16Sel);
6647 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, u32Limit);
6648 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, u32AccessRights);
6649 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_TR_BASE, u64Base);
6650 AssertRCReturn(rc, rc);
6651
6652 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_TR);
6653 Log4Func(("tr base=%#RX64 limit=%#RX32\n", pCtx->tr.u64Base, pCtx->tr.u32Limit));
6654 }
6655
6656 /*
6657 * Guest GDTR.
6658 */
6659 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_GDTR)
6660 {
6661 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_GDTR);
6662
6663 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, pCtx->gdtr.cbGdt);
6664 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, pCtx->gdtr.pGdt);
6665 AssertRCReturn(rc, rc);
6666
6667 /* Validate. */
6668 Assert(!(pCtx->gdtr.cbGdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6669
6670 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_GDTR);
6671 Log4Func(("gdtr base=%#RX64 limit=%#RX32\n", pCtx->gdtr.pGdt, pCtx->gdtr.cbGdt));
6672 }
6673
6674 /*
6675 * Guest LDTR.
6676 */
6677 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_LDTR)
6678 {
6679 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_LDTR);
6680
6681 /* The unusable bit is specific to VT-x, if it's a null selector mark it as an unusable segment. */
6682 uint32_t u32Access;
6683 if ( !pVmxTransient->fIsNestedGuest
6684 && !pCtx->ldtr.Attr.u)
6685 u32Access = X86DESCATTR_UNUSABLE;
6686 else
6687 u32Access = pCtx->ldtr.Attr.u;
6688
6689 rc = VMXWriteVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, pCtx->ldtr.Sel);
6690 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, pCtx->ldtr.u32Limit);
6691 rc |= VMXWriteVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, u32Access);
6692 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, pCtx->ldtr.u64Base);
6693 AssertRCReturn(rc, rc);
6694
6695 /* Validate. */
6696 if (!(u32Access & X86DESCATTR_UNUSABLE))
6697 {
6698 Assert(!(pCtx->ldtr.Sel & RT_BIT(2))); /* TI MBZ. */
6699 Assert(pCtx->ldtr.Attr.n.u4Type == 2); /* Type MB2 (LDT). */
6700 Assert(!pCtx->ldtr.Attr.n.u1DescType); /* System MBZ. */
6701 Assert(pCtx->ldtr.Attr.n.u1Present == 1); /* Present MB1. */
6702 Assert(!pCtx->ldtr.Attr.n.u4LimitHigh); /* 11:8 MBZ. */
6703 Assert(!(pCtx->ldtr.Attr.u & 0xfffe0000)); /* 31:17 MBZ. */
6704 Assert( (pCtx->ldtr.u32Limit & 0xfff) == 0xfff
6705 || !pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MBZ. */
6706 Assert( !(pCtx->ldtr.u32Limit & 0xfff00000)
6707 || pCtx->ldtr.Attr.n.u1Granularity); /* Granularity MB1. */
6708 }
6709
6710 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_LDTR);
6711 Log4Func(("ldtr base=%#RX64 limit=%#RX32\n", pCtx->ldtr.u64Base, pCtx->ldtr.u32Limit));
6712 }
6713
6714 /*
6715 * Guest IDTR.
6716 */
6717 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_IDTR)
6718 {
6719 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_IDTR);
6720
6721 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, pCtx->idtr.cbIdt);
6722 rc |= VMXWriteVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, pCtx->idtr.pIdt);
6723 AssertRCReturn(rc, rc);
6724
6725 /* Validate. */
6726 Assert(!(pCtx->idtr.cbIdt & 0xffff0000)); /* Bits 31:16 MBZ. */
6727
6728 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_IDTR);
6729 Log4Func(("idtr base=%#RX64 limit=%#RX32\n", pCtx->idtr.pIdt, pCtx->idtr.cbIdt));
6730 }
6731
6732 return VINF_SUCCESS;
6733}
6734
6735
6736/**
6737 * Exports certain guest MSRs into the VM-entry MSR-load and VM-exit MSR-store
6738 * areas.
6739 *
6740 * These MSRs will automatically be loaded to the host CPU on every successful
6741 * VM-entry and stored from the host CPU on every successful VM-exit.
6742 *
6743 * We creates/updates MSR slots for the host MSRs in the VM-exit MSR-load area. The
6744 * actual host MSR values are not- updated here for performance reasons. See
6745 * hmR0VmxExportHostMsrs().
6746 *
6747 * We also exports the guest sysenter MSRs into the guest-state area in the VMCS.
6748 *
6749 * @returns VBox status code.
6750 * @param pVCpu The cross context virtual CPU structure.
6751 * @param pVmxTransient The VMX-transient structure.
6752 *
6753 * @remarks No-long-jump zone!!!
6754 */
6755static int hmR0VmxExportGuestMsrs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6756{
6757 AssertPtr(pVCpu);
6758 AssertPtr(pVmxTransient);
6759
6760 PVM pVM = pVCpu->CTX_SUFF(pVM);
6761 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6762
6763 /*
6764 * MSRs that we use the auto-load/store MSR area in the VMCS.
6765 * For 64-bit hosts, we load/restore them lazily, see hmR0VmxLazyLoadGuestMsrs().
6766 * The host MSR values are updated when it's safe in hmR0VmxLazySaveHostMsrs().
6767 *
6768 * For nested-guests, the guests MSRs from the VM-entry MSR-load area are already
6769 * loaded (into the guest-CPU context) by the VMLAUNCH/VMRESUME instruction
6770 * emulation, nothing to do here.
6771 */
6772 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_GUEST_AUTO_MSRS)
6773 {
6774 if ( !pVmxTransient->fIsNestedGuest
6775 && pVM->hm.s.fAllow64BitGuests)
6776 {
6777#if HC_ARCH_BITS == 32
6778 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSCALL_MSRS | CPUMCTX_EXTRN_KERNEL_GS_BASE);
6779 Assert(!pVmxTransient->fIsNestedGuest);
6780
6781 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_LSTAR, pCtx->msrLSTAR, true, false);
6782 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_STAR, pCtx->msrSTAR, true, false);
6783 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_SF_MASK, pCtx->msrSFMASK, true, false);
6784 rc |= hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_KERNEL_GS_BASE, pCtx->msrKERNELGSBASE, true, false);
6785 AssertRCReturn(rc, rc);
6786#endif
6787 }
6788 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_VMX_GUEST_AUTO_MSRS);
6789 }
6790
6791 /*
6792 * Guest Sysenter MSRs.
6793 */
6794 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_MSR_MASK)
6795 {
6796 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_SYSENTER_MSRS);
6797
6798 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_CS_MSR)
6799 {
6800 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, pCtx->SysEnter.cs);
6801 AssertRCReturn(rc, rc);
6802 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_CS_MSR);
6803 }
6804
6805 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_EIP_MSR)
6806 {
6807 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, pCtx->SysEnter.eip);
6808 AssertRCReturn(rc, rc);
6809 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_EIP_MSR);
6810 }
6811
6812 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_SYSENTER_ESP_MSR)
6813 {
6814 int rc = VMXWriteVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, pCtx->SysEnter.esp);
6815 AssertRCReturn(rc, rc);
6816 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_SYSENTER_ESP_MSR);
6817 }
6818 }
6819
6820 /*
6821 * Guest/host EFER MSR.
6822 */
6823 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_EFER_MSR)
6824 {
6825 /* Whether we are using the VMCS to swap the EFER MSR must have been
6826 determined earlier while exporting VM-entry/VM-exit controls. */
6827 Assert(!(ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_VMX_ENTRY_EXIT_CTLS));
6828 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
6829
6830 if (hmR0VmxShouldSwapEferMsr(pVCpu))
6831 {
6832 /*
6833 * If the CPU supports VMCS controls for swapping EFER, use it. Otherwise, we have no option
6834 * but to use the auto-load store MSR area in the VMCS for swapping EFER. See @bugref{7368}.
6835 */
6836 if (pVM->hm.s.vmx.fSupportsVmcsEfer)
6837 {
6838 int rc = VMXWriteVmcs64(VMX_VMCS64_GUEST_EFER_FULL, pCtx->msrEFER);
6839 AssertRCReturn(rc, rc);
6840 }
6841 else
6842 {
6843 /*
6844 * We shall use the auto-load/store MSR area only for loading the EFER MSR but we must
6845 * continue to intercept guest read and write accesses to it, see @bugref{7386#c16}.
6846 */
6847 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER, pCtx->msrEFER,
6848 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6849 AssertRCReturn(rc, rc);
6850 }
6851 }
6852 else if (!pVM->hm.s.vmx.fSupportsVmcsEfer)
6853 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K6_EFER);
6854
6855 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_EFER_MSR);
6856 }
6857
6858 /*
6859 * Other MSRs.
6860 * Speculation Control (R/W).
6861 */
6862 if (ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged) & HM_CHANGED_GUEST_OTHER_MSRS)
6863 {
6864 HMVMX_CPUMCTX_ASSERT(pVCpu, HM_CHANGED_GUEST_OTHER_MSRS);
6865 if (pVM->cpum.ro.GuestFeatures.fIbrs)
6866 {
6867 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_IA32_SPEC_CTRL, CPUMGetGuestSpecCtrl(pVCpu),
6868 false /* fSetReadWrite */, false /* fUpdateHostMsr */);
6869 AssertRCReturn(rc, rc);
6870 }
6871 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~HM_CHANGED_GUEST_OTHER_MSRS);
6872 }
6873
6874 return VINF_SUCCESS;
6875}
6876
6877
6878/**
6879 * Selects up the appropriate function to run guest code.
6880 *
6881 * @returns VBox status code.
6882 * @param pVCpu The cross context virtual CPU structure.
6883 * @param pVmxTransient The VMX-transient structure.
6884 *
6885 * @remarks No-long-jump zone!!!
6886 */
6887static int hmR0VmxSelectVMRunHandler(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
6888{
6889 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6890 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
6891
6892 if (CPUMIsGuestInLongModeEx(pCtx))
6893 {
6894#ifndef VBOX_ENABLE_64_BITS_GUESTS
6895 return VERR_PGM_UNSUPPORTED_SHADOW_PAGING_MODE;
6896#endif
6897 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests); /* Guaranteed by hmR3InitFinalizeR0(). */
6898#if HC_ARCH_BITS == 32
6899 /* 32-bit host. We need to switch to 64-bit before running the 64-bit guest. */
6900 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
6901 {
6902#ifdef VBOX_STRICT
6903 if (pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6904 {
6905 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6906 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6907 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6908 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6909 ("fCtxChanged=%#RX64\n", fCtxChanged));
6910 }
6911#endif
6912 pVmcsInfo->pfnStartVM = VMXR0SwitcherStartVM64;
6913
6914 /* Mark that we've switched to 64-bit handler, we can't safely switch back to 32-bit for
6915 the rest of the VM run (until VM reset). See @bugref{8432#c7}. */
6916 pVmcsInfo->fSwitchedTo64on32 = true;
6917 Log4Func(("Selected 64-bit switcher\n"));
6918 }
6919#else
6920 /* 64-bit host. */
6921 pVmcsInfo->pfnStartVM = VMXR0StartVM64;
6922#endif
6923 }
6924 else
6925 {
6926 /* Guest is not in long mode, use the 32-bit handler. */
6927#if HC_ARCH_BITS == 32
6928 if ( pVmcsInfo->pfnStartVM != VMXR0StartVM32
6929 && !pVmcsInfo->fSwitchedTo64on32 /* If set, guest mode change does not imply switcher change. */
6930 && pVmcsInfo->pfnStartVM != NULL) /* Very first VM-entry would have saved host-state already, ignore it. */
6931 {
6932# ifdef VBOX_STRICT
6933 /* Currently, all mode changes sends us back to ring-3, so these should be set. See @bugref{6944}. */
6934 uint64_t const fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
6935 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
6936 AssertMsg(fCtxChanged & (HM_CHANGED_VMX_ENTRY_EXIT_CTLS | HM_CHANGED_GUEST_EFER_MSR),
6937 ("fCtxChanged=%#RX64\n", fCtxChanged));
6938# endif
6939 }
6940# ifdef VBOX_ENABLE_64_BITS_GUESTS
6941 /*
6942 * Keep using the 64-bit switcher even though we're in 32-bit because of bad Intel
6943 * design, see @bugref{8432#c7}. If real-on-v86 mode is active, clear the 64-bit
6944 * switcher flag now because we know the guest is in a sane state where it's safe
6945 * to use the 32-bit switcher. Otherwise, check the guest state if it's safe to use
6946 * the much faster 32-bit switcher again.
6947 */
6948 if (!pVmcsInfo->fSwitchedTo64on32)
6949 {
6950 if (pVmcsInfo->pfnStartVM != VMXR0StartVM32)
6951 Log4Func(("Selected 32-bit switcher\n"));
6952 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6953 }
6954 else
6955 {
6956 Assert(pVmcsInfo->pfnStartVM == VMXR0SwitcherStartVM64);
6957 if ( pVmcsInfo->RealMode.fRealOnV86Active
6958 || hmR0VmxIs32BitSwitcherSafe(pCtx))
6959 {
6960 pVmcsInfo->fSwitchedTo64on32 = false;
6961 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6962 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR
6963 | HM_CHANGED_VMX_ENTRY_EXIT_CTLS
6964 | HM_CHANGED_HOST_CONTEXT);
6965 Log4Func(("Selected 32-bit switcher (safe)\n"));
6966 }
6967 }
6968# else
6969 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6970# endif
6971#else
6972 pVmcsInfo->pfnStartVM = VMXR0StartVM32;
6973#endif
6974 }
6975 Assert(pVmcsInfo->pfnStartVM);
6976 return VINF_SUCCESS;
6977}
6978
6979
6980/**
6981 * Wrapper for running the guest code in VT-x.
6982 *
6983 * @returns VBox status code, no informational status codes.
6984 * @param pVCpu The cross context virtual CPU structure.
6985 * @param pVmxTransient The VMX-transient structure.
6986 *
6987 * @remarks No-long-jump zone!!!
6988 */
6989DECLINLINE(int) hmR0VmxRunGuest(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient)
6990{
6991 /* Mark that HM is the keeper of all guest-CPU registers now that we're going to execute guest code. */
6992 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
6993 pCtx->fExtrn |= HMVMX_CPUMCTX_EXTRN_ALL | CPUMCTX_EXTRN_KEEPER_HM;
6994
6995 /** @todo Add stats for VMRESUME vs VMLAUNCH. */
6996
6997 /*
6998 * 64-bit Windows uses XMM registers in the kernel as the Microsoft compiler expresses
6999 * floating-point operations using SSE instructions. Some XMM registers (XMM6-XMM15) are
7000 * callee-saved and thus the need for this XMM wrapper.
7001 *
7002 * See MSDN "Configuring Programs for 64-bit/x64 Software Conventions / Register Usage".
7003 */
7004 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
7005 bool const fResumeVM = RT_BOOL(pVmcsInfo->fVmcsState & VMX_V_VMCS_LAUNCH_STATE_LAUNCHED);
7006 PVM pVM = pVCpu->CTX_SUFF(pVM);
7007#ifdef VBOX_WITH_KERNEL_USING_XMM
7008 int rc = hmR0VMXStartVMWrapXMM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu, pVmcsInfo->pfnStartVM);
7009#else
7010 int rc = pVmcsInfo->pfnStartVM(fResumeVM, pCtx, &pVCpu->hm.s.vmx.VmcsCache, pVM, pVCpu);
7011#endif
7012 AssertMsg(rc <= VINF_SUCCESS, ("%Rrc\n", rc));
7013 return rc;
7014}
7015
7016
7017/**
7018 * Reports world-switch error and dumps some useful debug info.
7019 *
7020 * @param pVCpu The cross context virtual CPU structure.
7021 * @param rcVMRun The return code from VMLAUNCH/VMRESUME.
7022 * @param pVmxTransient The VMX-transient structure (only
7023 * exitReason updated).
7024 */
7025static void hmR0VmxReportWorldSwitchError(PVMCPU pVCpu, int rcVMRun, PVMXTRANSIENT pVmxTransient)
7026{
7027 Assert(pVCpu);
7028 Assert(pVmxTransient);
7029 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
7030
7031 Log4Func(("VM-entry failure: %Rrc\n", rcVMRun));
7032 switch (rcVMRun)
7033 {
7034 case VERR_VMX_INVALID_VMXON_PTR:
7035 AssertFailed();
7036 break;
7037 case VINF_SUCCESS: /* VMLAUNCH/VMRESUME succeeded but VM-entry failed... yeah, true story. */
7038 case VERR_VMX_UNABLE_TO_START_VM: /* VMLAUNCH/VMRESUME itself failed. */
7039 {
7040 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pVCpu->hm.s.vmx.LastError.u32ExitReason);
7041 rc |= VMXReadVmcs32(VMX_VMCS32_RO_VM_INSTR_ERROR, &pVCpu->hm.s.vmx.LastError.u32InstrError);
7042 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
7043 AssertRC(rc);
7044
7045 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
7046 /* LastError.idCurrentCpu was already updated in hmR0VmxPreRunGuestCommitted().
7047 Cannot do it here as we may have been long preempted. */
7048
7049#ifdef VBOX_STRICT
7050 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7051 Log4(("uExitReason %#RX32 (VmxTransient %#RX16)\n", pVCpu->hm.s.vmx.LastError.u32ExitReason,
7052 pVmxTransient->uExitReason));
7053 Log4(("Exit Qualification %#RX64\n", pVmxTransient->uExitQual));
7054 Log4(("InstrError %#RX32\n", pVCpu->hm.s.vmx.LastError.u32InstrError));
7055 if (pVCpu->hm.s.vmx.LastError.u32InstrError <= HMVMX_INSTR_ERROR_MAX)
7056 Log4(("InstrError Desc. \"%s\"\n", g_apszVmxInstrErrors[pVCpu->hm.s.vmx.LastError.u32InstrError]));
7057 else
7058 Log4(("InstrError Desc. Range exceeded %u\n", HMVMX_INSTR_ERROR_MAX));
7059 Log4(("Entered host CPU %u\n", pVCpu->hm.s.vmx.LastError.idEnteredCpu));
7060 Log4(("Current host CPU %u\n", pVCpu->hm.s.vmx.LastError.idCurrentCpu));
7061
7062 /* VMX control bits. */
7063 uint32_t u32Val;
7064 uint64_t u64Val;
7065 RTHCUINTREG uHCReg;
7066 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, &u32Val); AssertRC(rc);
7067 Log4(("VMX_VMCS32_CTRL_PIN_EXEC %#RX32\n", u32Val));
7068 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, &u32Val); AssertRC(rc);
7069 Log4(("VMX_VMCS32_CTRL_PROC_EXEC %#RX32\n", u32Val));
7070 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_SECONDARY_CTLS)
7071 {
7072 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, &u32Val); AssertRC(rc);
7073 Log4(("VMX_VMCS32_CTRL_PROC_EXEC2 %#RX32\n", u32Val));
7074 }
7075 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val); AssertRC(rc);
7076 Log4(("VMX_VMCS32_CTRL_ENTRY %#RX32\n", u32Val));
7077 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT, &u32Val); AssertRC(rc);
7078 Log4(("VMX_VMCS32_CTRL_EXIT %#RX32\n", u32Val));
7079 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_CR3_TARGET_COUNT, &u32Val); AssertRC(rc);
7080 Log4(("VMX_VMCS32_CTRL_CR3_TARGET_COUNT %#RX32\n", u32Val));
7081 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32Val); AssertRC(rc);
7082 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", u32Val));
7083 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, &u32Val); AssertRC(rc);
7084 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", u32Val));
7085 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, &u32Val); AssertRC(rc);
7086 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %u\n", u32Val));
7087 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, &u32Val); AssertRC(rc);
7088 Log4(("VMX_VMCS32_CTRL_TPR_THRESHOLD %u\n", u32Val));
7089 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT, &u32Val); AssertRC(rc);
7090 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_STORE_COUNT %u (guest MSRs)\n", u32Val));
7091 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7092 Log4(("VMX_VMCS32_CTRL_EXIT_MSR_LOAD_COUNT %u (host MSRs)\n", u32Val));
7093 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT, &u32Val); AssertRC(rc);
7094 Log4(("VMX_VMCS32_CTRL_ENTRY_MSR_LOAD_COUNT %u (guest MSRs)\n", u32Val));
7095 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, &u32Val); AssertRC(rc);
7096 Log4(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP %#RX32\n", u32Val));
7097 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, &u32Val); AssertRC(rc);
7098 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK %#RX32\n", u32Val));
7099 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, &u32Val); AssertRC(rc);
7100 Log4(("VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH %#RX32\n", u32Val));
7101 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
7102 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
7103 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
7104 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7105 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
7106 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
7107 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
7108 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
7109 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7110 {
7111 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
7112 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
7113 }
7114
7115 /* Guest bits. */
7116 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val); AssertRC(rc);
7117 Log4(("Old Guest Rip %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rip, u64Val));
7118 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val); AssertRC(rc);
7119 Log4(("Old Guest Rsp %#RX64 New %#RX64\n", pVCpu->cpum.GstCtx.rsp, u64Val));
7120 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val); AssertRC(rc);
7121 Log4(("Old Guest Rflags %#RX32 New %#RX32\n", pVCpu->cpum.GstCtx.eflags.u32, u32Val));
7122 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fVpid)
7123 {
7124 rc = VMXReadVmcs32(VMX_VMCS16_VPID, &u32Val); AssertRC(rc);
7125 Log4(("VMX_VMCS16_VPID %u\n", u32Val));
7126 }
7127
7128 /* Host bits. */
7129 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR0, &uHCReg); AssertRC(rc);
7130 Log4(("Host CR0 %#RHr\n", uHCReg));
7131 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR3, &uHCReg); AssertRC(rc);
7132 Log4(("Host CR3 %#RHr\n", uHCReg));
7133 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_CR4, &uHCReg); AssertRC(rc);
7134 Log4(("Host CR4 %#RHr\n", uHCReg));
7135
7136 RTGDTR HostGdtr;
7137 PCX86DESCHC pDesc;
7138 ASMGetGDTR(&HostGdtr);
7139 rc = VMXReadVmcs32(VMX_VMCS16_HOST_CS_SEL, &u32Val); AssertRC(rc);
7140 Log4(("Host CS %#08x\n", u32Val));
7141 if (u32Val < HostGdtr.cbGdt)
7142 {
7143 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7144 hmR0DumpDescriptor(pDesc, u32Val, "CS: ");
7145 }
7146
7147 rc = VMXReadVmcs32(VMX_VMCS16_HOST_DS_SEL, &u32Val); AssertRC(rc);
7148 Log4(("Host DS %#08x\n", u32Val));
7149 if (u32Val < HostGdtr.cbGdt)
7150 {
7151 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7152 hmR0DumpDescriptor(pDesc, u32Val, "DS: ");
7153 }
7154
7155 rc = VMXReadVmcs32(VMX_VMCS16_HOST_ES_SEL, &u32Val); AssertRC(rc);
7156 Log4(("Host ES %#08x\n", u32Val));
7157 if (u32Val < HostGdtr.cbGdt)
7158 {
7159 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7160 hmR0DumpDescriptor(pDesc, u32Val, "ES: ");
7161 }
7162
7163 rc = VMXReadVmcs32(VMX_VMCS16_HOST_FS_SEL, &u32Val); AssertRC(rc);
7164 Log4(("Host FS %#08x\n", u32Val));
7165 if (u32Val < HostGdtr.cbGdt)
7166 {
7167 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7168 hmR0DumpDescriptor(pDesc, u32Val, "FS: ");
7169 }
7170
7171 rc = VMXReadVmcs32(VMX_VMCS16_HOST_GS_SEL, &u32Val); AssertRC(rc);
7172 Log4(("Host GS %#08x\n", u32Val));
7173 if (u32Val < HostGdtr.cbGdt)
7174 {
7175 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7176 hmR0DumpDescriptor(pDesc, u32Val, "GS: ");
7177 }
7178
7179 rc = VMXReadVmcs32(VMX_VMCS16_HOST_SS_SEL, &u32Val); AssertRC(rc);
7180 Log4(("Host SS %#08x\n", u32Val));
7181 if (u32Val < HostGdtr.cbGdt)
7182 {
7183 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7184 hmR0DumpDescriptor(pDesc, u32Val, "SS: ");
7185 }
7186
7187 rc = VMXReadVmcs32(VMX_VMCS16_HOST_TR_SEL, &u32Val); AssertRC(rc);
7188 Log4(("Host TR %#08x\n", u32Val));
7189 if (u32Val < HostGdtr.cbGdt)
7190 {
7191 pDesc = (PCX86DESCHC)(HostGdtr.pGdt + (u32Val & X86_SEL_MASK));
7192 hmR0DumpDescriptor(pDesc, u32Val, "TR: ");
7193 }
7194
7195 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_TR_BASE, &uHCReg); AssertRC(rc);
7196 Log4(("Host TR Base %#RHv\n", uHCReg));
7197 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_GDTR_BASE, &uHCReg); AssertRC(rc);
7198 Log4(("Host GDTR Base %#RHv\n", uHCReg));
7199 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_IDTR_BASE, &uHCReg); AssertRC(rc);
7200 Log4(("Host IDTR Base %#RHv\n", uHCReg));
7201 rc = VMXReadVmcs32(VMX_VMCS32_HOST_SYSENTER_CS, &u32Val); AssertRC(rc);
7202 Log4(("Host SYSENTER CS %#08x\n", u32Val));
7203 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_EIP, &uHCReg); AssertRC(rc);
7204 Log4(("Host SYSENTER EIP %#RHv\n", uHCReg));
7205 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_SYSENTER_ESP, &uHCReg); AssertRC(rc);
7206 Log4(("Host SYSENTER ESP %#RHv\n", uHCReg));
7207 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RSP, &uHCReg); AssertRC(rc);
7208 Log4(("Host RSP %#RHv\n", uHCReg));
7209 rc = VMXReadVmcsHstN(VMX_VMCS_HOST_RIP, &uHCReg); AssertRC(rc);
7210 Log4(("Host RIP %#RHv\n", uHCReg));
7211# if HC_ARCH_BITS == 64
7212 Log4(("MSR_K6_EFER = %#RX64\n", ASMRdMsr(MSR_K6_EFER)));
7213 Log4(("MSR_K8_CSTAR = %#RX64\n", ASMRdMsr(MSR_K8_CSTAR)));
7214 Log4(("MSR_K8_LSTAR = %#RX64\n", ASMRdMsr(MSR_K8_LSTAR)));
7215 Log4(("MSR_K6_STAR = %#RX64\n", ASMRdMsr(MSR_K6_STAR)));
7216 Log4(("MSR_K8_SF_MASK = %#RX64\n", ASMRdMsr(MSR_K8_SF_MASK)));
7217 Log4(("MSR_K8_KERNEL_GS_BASE = %#RX64\n", ASMRdMsr(MSR_K8_KERNEL_GS_BASE)));
7218# endif
7219#endif /* VBOX_STRICT */
7220 break;
7221 }
7222
7223 default:
7224 /* Impossible */
7225 AssertMsgFailed(("hmR0VmxReportWorldSwitchError %Rrc (%#x)\n", rcVMRun, rcVMRun));
7226 break;
7227 }
7228}
7229
7230
7231#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
7232# ifndef VMX_USE_CACHED_VMCS_ACCESSES
7233# error "VMX_USE_CACHED_VMCS_ACCESSES not defined when it should be!"
7234# endif
7235
7236/**
7237 * Initialize the VMCS-Read cache.
7238 *
7239 * The VMCS cache is used for 32-bit hosts running 64-bit guests (except 32-bit
7240 * Darwin which runs with 64-bit paging in 32-bit mode) for 64-bit fields that
7241 * cannot be accessed in 32-bit mode. Some 64-bit fields -can- be accessed
7242 * (those that have a 32-bit FULL & HIGH part).
7243 *
7244 * @param pVCpu The cross context virtual CPU structure.
7245 */
7246static void hmR0VmxInitVmcsReadCache(PVMCPU pVCpu)
7247{
7248#define VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, idxField) \
7249 do { \
7250 Assert(pCache->Read.aField[idxField##_CACHE_IDX] == 0); \
7251 pCache->Read.aField[idxField##_CACHE_IDX] = idxField; \
7252 pCache->Read.aFieldVal[idxField##_CACHE_IDX] = 0; \
7253 ++cReadFields; \
7254 } while (0)
7255
7256 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7257 uint32_t cReadFields = 0;
7258
7259 /*
7260 * Don't remove the #if 0'd fields in this code. They're listed here for consistency
7261 * and serve to indicate exceptions to the rules.
7262 */
7263
7264 /* Guest-natural selector base fields. */
7265#if 0
7266 /* These are 32-bit in practice. See Intel spec. 2.5 "Control Registers". */
7267 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR0);
7268 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR4);
7269#endif
7270 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_ES_BASE);
7271 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CS_BASE);
7272 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SS_BASE);
7273 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_DS_BASE);
7274 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_FS_BASE);
7275 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GS_BASE);
7276 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_LDTR_BASE);
7277 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_TR_BASE);
7278 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_GDTR_BASE);
7279 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_IDTR_BASE);
7280 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RSP);
7281 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_RIP);
7282#if 0
7283 /* Unused natural width guest-state fields. */
7284 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS);
7285 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3); /* Handled in nested paging case */
7286#endif
7287 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_ESP);
7288 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_SYSENTER_EIP);
7289
7290 /* 64-bit guest-state fields; unused as we use two 32-bit VMREADs for
7291 these 64-bit fields (using "FULL" and "HIGH" fields). */
7292#if 0
7293 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL);
7294 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_DEBUGCTL_FULL);
7295 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PAT_FULL);
7296 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_EFER_FULL);
7297 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL);
7298 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE0_FULL);
7299 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE1_FULL);
7300 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE2_FULL);
7301 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS64_GUEST_PDPTE3_FULL);
7302#endif
7303
7304 /* Natural width guest-state fields. */
7305 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_EXIT_QUALIFICATION);
7306 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_RO_GUEST_LINEAR_ADDR);
7307
7308 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
7309 {
7310 VMXLOCAL_INIT_READ_CACHE_FIELD(pCache, VMX_VMCS_GUEST_CR3);
7311 AssertMsg(cReadFields == VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields,
7312 VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX));
7313 pCache->Read.cValidEntries = VMX_VMCS_MAX_NESTED_PAGING_CACHE_IDX;
7314 }
7315 else
7316 {
7317 AssertMsg(cReadFields == VMX_VMCS_MAX_CACHE_IDX, ("cReadFields=%u expected %u\n", cReadFields, VMX_VMCS_MAX_CACHE_IDX));
7318 pCache->Read.cValidEntries = VMX_VMCS_MAX_CACHE_IDX;
7319 }
7320
7321#undef VMXLOCAL_INIT_READ_CACHE_FIELD
7322}
7323
7324
7325/**
7326 * Writes a field into the VMCS. This can either directly invoke a VMWRITE or
7327 * queue up the VMWRITE by using the VMCS write cache (on 32-bit hosts, except
7328 * darwin, running 64-bit guests).
7329 *
7330 * @returns VBox status code.
7331 * @param pVCpu The cross context virtual CPU structure.
7332 * @param idxField The VMCS field encoding.
7333 * @param u64Val 16, 32 or 64-bit value.
7334 */
7335VMMR0DECL(int) VMXWriteVmcs64Ex(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7336{
7337 AssertPtr(pVCpu);
7338 int rc;
7339 switch (idxField)
7340 {
7341 /*
7342 * These fields consists of a "FULL" and a "HIGH" part which can be written to individually.
7343 */
7344 /* 64-bit Control fields. */
7345 case VMX_VMCS64_CTRL_IO_BITMAP_A_FULL:
7346 case VMX_VMCS64_CTRL_IO_BITMAP_B_FULL:
7347 case VMX_VMCS64_CTRL_MSR_BITMAP_FULL:
7348 case VMX_VMCS64_CTRL_EXIT_MSR_STORE_FULL:
7349 case VMX_VMCS64_CTRL_EXIT_MSR_LOAD_FULL:
7350 case VMX_VMCS64_CTRL_ENTRY_MSR_LOAD_FULL:
7351 case VMX_VMCS64_CTRL_EXEC_VMCS_PTR_FULL:
7352 case VMX_VMCS64_CTRL_TSC_OFFSET_FULL:
7353 case VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL:
7354 case VMX_VMCS64_CTRL_APIC_ACCESSADDR_FULL:
7355 case VMX_VMCS64_CTRL_VMFUNC_CTRLS_FULL:
7356 case VMX_VMCS64_CTRL_EPTP_FULL:
7357 case VMX_VMCS64_CTRL_EPTP_LIST_FULL:
7358 /* 64-bit Guest-state fields. */
7359 case VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL:
7360 case VMX_VMCS64_GUEST_DEBUGCTL_FULL:
7361 case VMX_VMCS64_GUEST_PAT_FULL:
7362 case VMX_VMCS64_GUEST_EFER_FULL:
7363 case VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL:
7364 case VMX_VMCS64_GUEST_PDPTE0_FULL:
7365 case VMX_VMCS64_GUEST_PDPTE1_FULL:
7366 case VMX_VMCS64_GUEST_PDPTE2_FULL:
7367 case VMX_VMCS64_GUEST_PDPTE3_FULL:
7368 /* 64-bit Host-state fields. */
7369 case VMX_VMCS64_HOST_PAT_FULL:
7370 case VMX_VMCS64_HOST_EFER_FULL:
7371 case VMX_VMCS64_HOST_PERF_GLOBAL_CTRL_FULL:
7372 {
7373 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7374 rc |= VMXWriteVmcs32(idxField + 1, RT_HI_U32(u64Val));
7375 break;
7376 }
7377
7378 /*
7379 * These fields do not have high and low parts. Queue up the VMWRITE by using the VMCS write-cache (for 64-bit
7380 * values). When we switch the host to 64-bit mode for running 64-bit guests, these VMWRITEs get executed then.
7381 */
7382 /* Natural-width Guest-state fields. */
7383 case VMX_VMCS_GUEST_CR3:
7384 case VMX_VMCS_GUEST_ES_BASE:
7385 case VMX_VMCS_GUEST_CS_BASE:
7386 case VMX_VMCS_GUEST_SS_BASE:
7387 case VMX_VMCS_GUEST_DS_BASE:
7388 case VMX_VMCS_GUEST_FS_BASE:
7389 case VMX_VMCS_GUEST_GS_BASE:
7390 case VMX_VMCS_GUEST_LDTR_BASE:
7391 case VMX_VMCS_GUEST_TR_BASE:
7392 case VMX_VMCS_GUEST_GDTR_BASE:
7393 case VMX_VMCS_GUEST_IDTR_BASE:
7394 case VMX_VMCS_GUEST_RSP:
7395 case VMX_VMCS_GUEST_RIP:
7396 case VMX_VMCS_GUEST_SYSENTER_ESP:
7397 case VMX_VMCS_GUEST_SYSENTER_EIP:
7398 {
7399 if (!(RT_HI_U32(u64Val)))
7400 {
7401 /* If this field is 64-bit, VT-x will zero out the top bits. */
7402 rc = VMXWriteVmcs32(idxField, RT_LO_U32(u64Val));
7403 }
7404 else
7405 {
7406 /* Assert that only the 32->64 switcher case should ever come here. */
7407 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fAllow64BitGuests);
7408 rc = VMXWriteCachedVmcsEx(pVCpu, idxField, u64Val);
7409 }
7410 break;
7411 }
7412
7413 default:
7414 {
7415 AssertMsgFailed(("VMXWriteVmcs64Ex: Invalid field %#RX32 (pVCpu=%p u64Val=%#RX64)\n", idxField, pVCpu, u64Val));
7416 pVCpu->hm.s.u32HMError = idxField;
7417 rc = VERR_INVALID_PARAMETER;
7418 break;
7419 }
7420 }
7421 AssertRCReturn(rc, rc);
7422 return rc;
7423}
7424
7425
7426/**
7427 * Queue up a VMWRITE by using the VMCS write cache.
7428 * This is only used on 32-bit hosts (except darwin) for 64-bit guests.
7429 *
7430 * @param pVCpu The cross context virtual CPU structure.
7431 * @param idxField The VMCS field encoding.
7432 * @param u64Val 16, 32 or 64-bit value.
7433 */
7434VMMR0DECL(int) VMXWriteCachedVmcsEx(PVMCPU pVCpu, uint32_t idxField, uint64_t u64Val)
7435{
7436 AssertPtr(pVCpu);
7437 PVMXVMCSCACHE pCache = &pVCpu->hm.s.vmx.VmcsCache;
7438
7439 AssertMsgReturn(pCache->Write.cValidEntries < VMX_VMCS_CACHE_MAX_ENTRY - 1,
7440 ("entries=%u\n", pCache->Write.cValidEntries), VERR_ACCESS_DENIED);
7441
7442 /* Make sure there are no duplicates. */
7443 for (uint32_t i = 0; i < pCache->Write.cValidEntries; i++)
7444 {
7445 if (pCache->Write.aField[i] == idxField)
7446 {
7447 pCache->Write.aFieldVal[i] = u64Val;
7448 return VINF_SUCCESS;
7449 }
7450 }
7451
7452 pCache->Write.aField[pCache->Write.cValidEntries] = idxField;
7453 pCache->Write.aFieldVal[pCache->Write.cValidEntries] = u64Val;
7454 pCache->Write.cValidEntries++;
7455 return VINF_SUCCESS;
7456}
7457#endif /* HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS) */
7458
7459
7460/**
7461 * Sets up the usage of TSC-offsetting and updates the VMCS.
7462 *
7463 * If offsetting is not possible, cause VM-exits on RDTSC(P)s. Also sets up the
7464 * VMX-preemption timer.
7465 *
7466 * @returns VBox status code.
7467 * @param pVCpu The cross context virtual CPU structure.
7468 * @param pVmxTransient The VMX-transient structure.
7469 *
7470 * @remarks No-long-jump zone!!!
7471 */
7472static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
7473{
7474 bool fOffsettedTsc;
7475 bool fParavirtTsc;
7476 uint64_t uTscOffset;
7477 PVM pVM = pVCpu->CTX_SUFF(pVM);
7478 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
7479
7480 if (pVM->hm.s.vmx.fUsePreemptTimer)
7481 {
7482 uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &uTscOffset, &fOffsettedTsc, &fParavirtTsc);
7483
7484 /* Make sure the returned values have sane upper and lower boundaries. */
7485 uint64_t u64CpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
7486 cTicksToDeadline = RT_MIN(cTicksToDeadline, u64CpuHz / 64); /* 1/64th of a second */
7487 cTicksToDeadline = RT_MAX(cTicksToDeadline, u64CpuHz / 2048); /* 1/2048th of a second */
7488 cTicksToDeadline >>= pVM->hm.s.vmx.cPreemptTimerShift;
7489
7490 /** @todo r=ramshankar: We need to find a way to integrate nested-guest
7491 * preemption timers here. We probably need to clamp the preemption timer,
7492 * after converting the timer value to the host. */
7493 uint32_t cPreemptionTickCount = (uint32_t)RT_MIN(cTicksToDeadline, UINT32_MAX - 16);
7494 int rc = VMXWriteVmcs32(VMX_VMCS32_PREEMPT_TIMER_VALUE, cPreemptionTickCount);
7495 AssertRC(rc);
7496 }
7497 else
7498 fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &uTscOffset, &fParavirtTsc);
7499
7500 if (fParavirtTsc)
7501 {
7502 /* Currently neither Hyper-V nor KVM need to update their paravirt. TSC
7503 information before every VM-entry, hence disable it for performance sake. */
7504#if 0
7505 int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
7506 AssertRC(rc);
7507#endif
7508 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
7509 }
7510
7511 if ( fOffsettedTsc
7512 && RT_LIKELY(!pVCpu->hm.s.fDebugWantRdTscExit))
7513 {
7514 if (pVmxTransient->fIsNestedGuest)
7515 uTscOffset = CPUMApplyNestedGuestTscOffset(pVCpu, uTscOffset);
7516 hmR0VmxSetTscOffsetVmcs(pVCpu, pVmcsInfo, uTscOffset);
7517 hmR0VmxRemoveProcCtlsVmcs(pVCpu, pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7518 }
7519 else
7520 {
7521 /* We can't use TSC-offsetting (non-fixed TSC, warp drive active etc.), VM-exit on RDTSC(P). */
7522 hmR0VmxSetProcCtlsVmcs(pVmxTransient, VMX_PROC_CTLS_RDTSC_EXIT);
7523 }
7524}
7525
7526
7527/**
7528 * Gets the IEM exception flags for the specified vector and IDT vectoring /
7529 * VM-exit interruption info type.
7530 *
7531 * @returns The IEM exception flags.
7532 * @param uVector The event vector.
7533 * @param uVmxEventType The VMX event type.
7534 *
7535 * @remarks This function currently only constructs flags required for
7536 * IEMEvaluateRecursiveXcpt and not the complete flags (e.g, error-code
7537 * and CR2 aspects of an exception are not included).
7538 */
7539static uint32_t hmR0VmxGetIemXcptFlags(uint8_t uVector, uint32_t uVmxEventType)
7540{
7541 uint32_t fIemXcptFlags;
7542 switch (uVmxEventType)
7543 {
7544 case VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT:
7545 case VMX_IDT_VECTORING_INFO_TYPE_NMI:
7546 fIemXcptFlags = IEM_XCPT_FLAGS_T_CPU_XCPT;
7547 break;
7548
7549 case VMX_IDT_VECTORING_INFO_TYPE_EXT_INT:
7550 fIemXcptFlags = IEM_XCPT_FLAGS_T_EXT_INT;
7551 break;
7552
7553 case VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT:
7554 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT | IEM_XCPT_FLAGS_ICEBP_INSTR;
7555 break;
7556
7557 case VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT:
7558 {
7559 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7560 if (uVector == X86_XCPT_BP)
7561 fIemXcptFlags |= IEM_XCPT_FLAGS_BP_INSTR;
7562 else if (uVector == X86_XCPT_OF)
7563 fIemXcptFlags |= IEM_XCPT_FLAGS_OF_INSTR;
7564 else
7565 {
7566 fIemXcptFlags = 0;
7567 AssertMsgFailed(("Unexpected vector for software exception. uVector=%#x", uVector));
7568 }
7569 break;
7570 }
7571
7572 case VMX_IDT_VECTORING_INFO_TYPE_SW_INT:
7573 fIemXcptFlags = IEM_XCPT_FLAGS_T_SOFT_INT;
7574 break;
7575
7576 default:
7577 fIemXcptFlags = 0;
7578 AssertMsgFailed(("Unexpected vector type! uVmxEventType=%#x uVector=%#x", uVmxEventType, uVector));
7579 break;
7580 }
7581 return fIemXcptFlags;
7582}
7583
7584
7585/**
7586 * Sets an event as a pending event to be injected into the guest.
7587 *
7588 * @param pVCpu The cross context virtual CPU structure.
7589 * @param u32IntInfo The VM-entry interruption-information field.
7590 * @param cbInstr The VM-entry instruction length in bytes (for software
7591 * interrupts, exceptions and privileged software
7592 * exceptions).
7593 * @param u32ErrCode The VM-entry exception error code.
7594 * @param GCPtrFaultAddress The fault-address (CR2) in case it's a
7595 * page-fault.
7596 */
7597DECLINLINE(void) hmR0VmxSetPendingEvent(PVMCPU pVCpu, uint32_t u32IntInfo, uint32_t cbInstr, uint32_t u32ErrCode,
7598 RTGCUINTPTR GCPtrFaultAddress)
7599{
7600 Assert(!pVCpu->hm.s.Event.fPending);
7601 pVCpu->hm.s.Event.fPending = true;
7602 pVCpu->hm.s.Event.u64IntInfo = u32IntInfo;
7603 pVCpu->hm.s.Event.u32ErrCode = u32ErrCode;
7604 pVCpu->hm.s.Event.cbInstr = cbInstr;
7605 pVCpu->hm.s.Event.GCPtrFaultAddress = GCPtrFaultAddress;
7606}
7607
7608
7609/**
7610 * Sets an external interrupt as pending-for-injection into the VM.
7611 *
7612 * @param pVCpu The cross context virtual CPU structure.
7613 * @param u8Interrupt The external interrupt vector.
7614 */
7615DECLINLINE(void) hmR0VmxSetPendingExtInt(PVMCPU pVCpu, uint8_t u8Interrupt)
7616{
7617 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_EXIT_INT_INFO_VECTOR, u8Interrupt)
7618 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
7619 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7620 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7621 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7622}
7623
7624
7625/**
7626 * Sets an NMI (\#NMI) exception as pending-for-injection into the VM.
7627 *
7628 * @param pVCpu The cross context virtual CPU structure.
7629 */
7630DECLINLINE(void) hmR0VmxSetPendingXcptNmi(PVMCPU pVCpu)
7631{
7632 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_NMI)
7633 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_NMI)
7634 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7635 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7636 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7637}
7638
7639
7640/**
7641 * Sets a double-fault (\#DF) exception as pending-for-injection into the VM.
7642 *
7643 * @param pVCpu The cross context virtual CPU structure.
7644 */
7645DECLINLINE(void) hmR0VmxSetPendingXcptDF(PVMCPU pVCpu)
7646{
7647 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
7648 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7649 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7650 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7651 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7652}
7653
7654
7655/**
7656 * Sets an invalid-opcode (\#UD) exception as pending-for-injection into the VM.
7657 *
7658 * @param pVCpu The cross context virtual CPU structure.
7659 */
7660DECLINLINE(void) hmR0VmxSetPendingXcptUD(PVMCPU pVCpu)
7661{
7662 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_UD)
7663 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7664 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7665 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7666 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7667}
7668
7669
7670/**
7671 * Sets a debug (\#DB) exception as pending-for-injection into the VM.
7672 *
7673 * @param pVCpu The cross context virtual CPU structure.
7674 */
7675DECLINLINE(void) hmR0VmxSetPendingXcptDB(PVMCPU pVCpu)
7676{
7677 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DB)
7678 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7679 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
7680 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7681 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, 0 /* u32ErrCode */, 0 /* GCPtrFaultAddress */);
7682}
7683
7684
7685#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
7686/**
7687 * Sets a general-protection (\#GP) exception as pending-for-injection into the VM.
7688 *
7689 * @param pVCpu The cross context virtual CPU structure.
7690 * @param u32ErrCode The error code for the general-protection exception.
7691 */
7692DECLINLINE(void) hmR0VmxSetPendingXcptGP(PVMCPU pVCpu, uint32_t u32ErrCode)
7693{
7694 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
7695 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7696 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7697 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7698 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7699}
7700
7701
7702/**
7703 * Sets a stack (\#SS) exception as pending-for-injection into the VM.
7704 *
7705 * @param pVCpu The cross context virtual CPU structure.
7706 * @param u32ErrCode The error code for the stack exception.
7707 */
7708DECLINLINE(void) hmR0VmxSetPendingXcptSS(PVMCPU pVCpu, uint32_t u32ErrCode)
7709{
7710 uint32_t const u32IntInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_SS)
7711 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_EXIT_INT_INFO_TYPE_HW_XCPT)
7712 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 1)
7713 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
7714 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, 0 /* cbInstr */, u32ErrCode, 0 /* GCPtrFaultAddress */);
7715}
7716#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
7717
7718
7719static void hmR0VmxFixUnusableSegRegAttr(PVMCPU pVCpu, PCPUMSELREG pSelReg, uint32_t idxSel)
7720{
7721 Assert(pSelReg->Attr.u & X86DESCATTR_UNUSABLE);
7722
7723 /*
7724 * If VT-x marks the segment as unusable, most other bits remain undefined:
7725 * - For CS the L, D and G bits have meaning.
7726 * - For SS the DPL has meaning (it -is- the CPL for Intel and VBox).
7727 * - For the remaining data segments no bits are defined.
7728 *
7729 * The present bit and the unusable bit has been observed to be set at the
7730 * same time (the selector was supposed to be invalid as we started executing
7731 * a V8086 interrupt in ring-0).
7732 *
7733 * What should be important for the rest of the VBox code, is that the P bit is
7734 * cleared. Some of the other VBox code recognizes the unusable bit, but
7735 * AMD-V certainly don't, and REM doesn't really either. So, to be on the
7736 * safe side here, we'll strip off P and other bits we don't care about. If
7737 * any code breaks because Attr.u != 0 when Sel < 4, it should be fixed.
7738 *
7739 * See Intel spec. 27.3.2 "Saving Segment Registers and Descriptor-Table Registers".
7740 */
7741#ifdef VBOX_STRICT
7742 uint32_t const uAttr = pSelReg->Attr.u;
7743#endif
7744
7745 /* Masking off: X86DESCATTR_P, X86DESCATTR_LIMIT_HIGH, and X86DESCATTR_AVL. The latter two are really irrelevant. */
7746 pSelReg->Attr.u &= X86DESCATTR_UNUSABLE | X86DESCATTR_L | X86DESCATTR_D | X86DESCATTR_G
7747 | X86DESCATTR_DPL | X86DESCATTR_TYPE | X86DESCATTR_DT;
7748
7749#ifdef VBOX_STRICT
7750 VMMRZCallRing3Disable(pVCpu);
7751 Log4Func(("Unusable %#x: sel=%#x attr=%#x -> %#x\n", idxSel, pSelReg->Sel, uAttr, pSelReg->Attr.u));
7752# ifdef DEBUG_bird
7753 AssertMsg((uAttr & ~X86DESCATTR_P) == pSelReg->Attr.u,
7754 ("%#x: %#x != %#x (sel=%#x base=%#llx limit=%#x)\n",
7755 idxSel, uAttr, pSelReg->Attr.u, pSelReg->Sel, pSelReg->u64Base, pSelReg->u32Limit));
7756# endif
7757 VMMRZCallRing3Enable(pVCpu);
7758 NOREF(uAttr);
7759#endif
7760 RT_NOREF2(pVCpu, idxSel);
7761}
7762
7763
7764/**
7765 * Imports a guest segment register from the current VMCS into the guest-CPU
7766 * context.
7767 *
7768 * @returns VBox status code.
7769 * @param pVCpu The cross context virtual CPU structure.
7770 * @param iSegReg The segment register number (X86_SREG_XXX).
7771 *
7772 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7773 * do not log!
7774 */
7775static int hmR0VmxImportGuestSegReg(PVMCPU pVCpu, uint8_t iSegReg)
7776{
7777 Assert(iSegReg < X86_SREG_COUNT);
7778
7779 uint32_t const idxSel = g_aVmcsSegSel[iSegReg];
7780 uint32_t const idxLimit = g_aVmcsSegLimit[iSegReg];
7781 uint32_t const idxAttr = g_aVmcsSegAttr[iSegReg];
7782#ifdef VMX_USE_CACHED_VMCS_ACCESSES
7783 uint32_t const idxBase = g_aVmcsCacheSegBase[iSegReg];
7784#else
7785 uint32_t const idxBase = g_aVmcsSegBase[iSegReg];
7786#endif
7787 uint64_t u64Base;
7788 uint32_t u32Sel, u32Limit, u32Attr;
7789 int rc = VMXReadVmcs32(idxSel, &u32Sel);
7790 rc |= VMXReadVmcs32(idxLimit, &u32Limit);
7791 rc |= VMXReadVmcs32(idxAttr, &u32Attr);
7792 rc |= VMXReadVmcsGstNByIdxVal(idxBase, &u64Base);
7793 if (RT_SUCCESS(rc))
7794 {
7795 PCPUMSELREG pSelReg = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
7796 pSelReg->Sel = u32Sel;
7797 pSelReg->ValidSel = u32Sel;
7798 pSelReg->fFlags = CPUMSELREG_FLAGS_VALID;
7799 pSelReg->u32Limit = u32Limit;
7800 pSelReg->u64Base = u64Base;
7801 pSelReg->Attr.u = u32Attr;
7802 if (u32Attr & X86DESCATTR_UNUSABLE)
7803 hmR0VmxFixUnusableSegRegAttr(pVCpu, pSelReg, idxSel);
7804 }
7805 return rc;
7806}
7807
7808
7809/**
7810 * Imports the guest LDTR from the current VMCS into the guest-CPU context.
7811 *
7812 * @returns VBox status code.
7813 * @param pVCpu The cross context virtual CPU structure.
7814 *
7815 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7816 * do not log!
7817 */
7818static int hmR0VmxImportGuestLdtr(PVMCPU pVCpu)
7819{
7820 uint64_t u64Base;
7821 uint32_t u32Sel, u32Limit, u32Attr;
7822 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_LDTR_SEL, &u32Sel);
7823 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_LIMIT, &u32Limit);
7824 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_LDTR_ACCESS_RIGHTS, &u32Attr);
7825 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_LDTR_BASE, &u64Base);
7826 if (RT_SUCCESS(rc))
7827 {
7828 pVCpu->cpum.GstCtx.ldtr.Sel = u32Sel;
7829 pVCpu->cpum.GstCtx.ldtr.ValidSel = u32Sel;
7830 pVCpu->cpum.GstCtx.ldtr.fFlags = CPUMSELREG_FLAGS_VALID;
7831 pVCpu->cpum.GstCtx.ldtr.u32Limit = u32Limit;
7832 pVCpu->cpum.GstCtx.ldtr.u64Base = u64Base;
7833 pVCpu->cpum.GstCtx.ldtr.Attr.u = u32Attr;
7834 if (u32Attr & X86DESCATTR_UNUSABLE)
7835 hmR0VmxFixUnusableSegRegAttr(pVCpu, &pVCpu->cpum.GstCtx.ldtr, VMX_VMCS16_GUEST_LDTR_SEL);
7836 }
7837 return rc;
7838}
7839
7840
7841/**
7842 * Imports the guest TR from the current VMCS into the guest-CPU context.
7843 *
7844 * @returns VBox status code.
7845 * @param pVCpu The cross context virtual CPU structure.
7846 *
7847 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7848 * do not log!
7849 */
7850static int hmR0VmxImportGuestTr(PVMCPU pVCpu)
7851{
7852 uint32_t u32Sel, u32Limit, u32Attr;
7853 uint64_t u64Base;
7854 int rc = VMXReadVmcs32(VMX_VMCS16_GUEST_TR_SEL, &u32Sel);
7855 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_LIMIT, &u32Limit);
7856 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_TR_ACCESS_RIGHTS, &u32Attr);
7857 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_TR_BASE, &u64Base);
7858 AssertRCReturn(rc, rc);
7859
7860 pVCpu->cpum.GstCtx.tr.Sel = u32Sel;
7861 pVCpu->cpum.GstCtx.tr.ValidSel = u32Sel;
7862 pVCpu->cpum.GstCtx.tr.fFlags = CPUMSELREG_FLAGS_VALID;
7863 pVCpu->cpum.GstCtx.tr.u32Limit = u32Limit;
7864 pVCpu->cpum.GstCtx.tr.u64Base = u64Base;
7865 pVCpu->cpum.GstCtx.tr.Attr.u = u32Attr;
7866 /* TR is the only selector that can never be unusable. */
7867 Assert(!(u32Attr & X86DESCATTR_UNUSABLE));
7868 return VINF_SUCCESS;
7869}
7870
7871
7872/**
7873 * Imports the guest RIP from the VMCS back into the guest-CPU context.
7874 *
7875 * @returns VBox status code.
7876 * @param pVCpu The cross context virtual CPU structure.
7877 *
7878 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7879 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7880 * instead!!!
7881 */
7882static int hmR0VmxImportGuestRip(PVMCPU pVCpu)
7883{
7884 uint64_t u64Val;
7885 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7886 if (pCtx->fExtrn & CPUMCTX_EXTRN_RIP)
7887 {
7888 int rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RIP, &u64Val);
7889 if (RT_SUCCESS(rc))
7890 {
7891 pCtx->rip = u64Val;
7892 EMR0HistoryUpdatePC(pVCpu, pCtx->rip, false);
7893 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RIP;
7894 }
7895 return rc;
7896 }
7897 return VINF_SUCCESS;
7898}
7899
7900
7901/**
7902 * Imports the guest RFLAGS from the VMCS back into the guest-CPU context.
7903 *
7904 * @returns VBox status code.
7905 * @param pVCpu The cross context virtual CPU structure.
7906 * @param pVmcsInfo The VMCS info. object.
7907 *
7908 * @remarks Called with interrupts and/or preemption disabled, should not assert!
7909 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7910 * instead!!!
7911 */
7912static int hmR0VmxImportGuestRFlags(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7913{
7914 uint32_t u32Val;
7915 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
7916 if (pCtx->fExtrn & CPUMCTX_EXTRN_RFLAGS)
7917 {
7918 int rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Val);
7919 if (RT_SUCCESS(rc))
7920 {
7921 pCtx->eflags.u32 = u32Val;
7922
7923 /* Restore eflags for real-on-v86-mode hack. */
7924 if (pVmcsInfo->RealMode.fRealOnV86Active)
7925 {
7926 pCtx->eflags.Bits.u1VM = 0;
7927 pCtx->eflags.Bits.u2IOPL = pVmcsInfo->RealMode.Eflags.Bits.u2IOPL;
7928 }
7929 }
7930 pCtx->fExtrn &= ~CPUMCTX_EXTRN_RFLAGS;
7931 return rc;
7932 }
7933 return VINF_SUCCESS;
7934}
7935
7936
7937/**
7938 * Imports the guest interruptibility-state from the VMCS back into the guest-CPU
7939 * context.
7940 *
7941 * @returns VBox status code.
7942 * @param pVCpu The cross context virtual CPU structure.
7943 * @param pVmcsInfo The VMCS info. object.
7944 *
7945 * @remarks Called with interrupts and/or preemption disabled, try not to assert and
7946 * do not log!
7947 * @remarks Do -not- call this function directly, use hmR0VmxImportGuestState()
7948 * instead!!!
7949 */
7950static int hmR0VmxImportGuestIntrState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
7951{
7952 uint32_t u32Val;
7953 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32Val);
7954 if (RT_SUCCESS(rc))
7955 {
7956 if (!u32Val)
7957 {
7958 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7959 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7960
7961 CPUMSetGuestNmiBlocking(pVCpu, false);
7962 }
7963 else
7964 {
7965 /*
7966 * We must import RIP here to set our EM interrupt-inhibited state.
7967 * We also import RFLAGS as our code that evaluates pending interrupts
7968 * before VM-entry requires it.
7969 */
7970 rc = hmR0VmxImportGuestRip(pVCpu);
7971 rc |= hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
7972 if (RT_SUCCESS(rc))
7973 {
7974 if (u32Val & (VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS | VMX_VMCS_GUEST_INT_STATE_BLOCK_STI))
7975 EMSetInhibitInterruptsPC(pVCpu, pVCpu->cpum.GstCtx.rip);
7976 else if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
7977 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
7978
7979 bool const fNmiBlocking = RT_BOOL(u32Val & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
7980 CPUMSetGuestNmiBlocking(pVCpu, fNmiBlocking);
7981 }
7982 }
7983 }
7984 return rc;
7985}
7986
7987
7988/**
7989 * Worker for VMXR0ImportStateOnDemand.
7990 *
7991 * @returns VBox status code.
7992 * @param pVCpu The cross context virtual CPU structure.
7993 * @param pVmcsInfo The VMCS info. object.
7994 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
7995 */
7996static int hmR0VmxImportGuestState(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint64_t fWhat)
7997{
7998#define VMXLOCAL_BREAK_RC(a_rc) \
7999 if (RT_SUCCESS(a_rc)) \
8000 { } \
8001 else \
8002 break
8003
8004 int rc = VINF_SUCCESS;
8005 PVM pVM = pVCpu->CTX_SUFF(pVM);
8006 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8007 uint64_t u64Val;
8008 uint32_t u32Val;
8009
8010 /*
8011 * Note! This is hack to workaround a mysterious BSOD observed with release builds
8012 * on Windows 10 64-bit hosts. Profile and debug builds are not affected and
8013 * neither are other host platforms.
8014 *
8015 * Committing this temporarily as it prevents BSOD.
8016 *
8017 * Update: This is very likely a compiler optimization bug, see @bugref{9180}.
8018 */
8019#ifdef RT_OS_WINDOWS
8020 if (pVM == 0 || pVM == (void *)(uintptr_t)-1)
8021 return VERR_HM_IPE_1;
8022#endif
8023
8024 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatImportGuestState, x);
8025
8026 /*
8027 * We disable interrupts to make the updating of the state and in particular
8028 * the fExtrn modification atomic wrt to preemption hooks.
8029 */
8030 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
8031
8032 fWhat &= pCtx->fExtrn;
8033 if (fWhat)
8034 {
8035 do
8036 {
8037 if (fWhat & CPUMCTX_EXTRN_RIP)
8038 {
8039 rc = hmR0VmxImportGuestRip(pVCpu);
8040 VMXLOCAL_BREAK_RC(rc);
8041 }
8042
8043 if (fWhat & CPUMCTX_EXTRN_RFLAGS)
8044 {
8045 rc = hmR0VmxImportGuestRFlags(pVCpu, pVmcsInfo);
8046 VMXLOCAL_BREAK_RC(rc);
8047 }
8048
8049 if (fWhat & CPUMCTX_EXTRN_HM_VMX_INT_STATE)
8050 {
8051 rc = hmR0VmxImportGuestIntrState(pVCpu, pVmcsInfo);
8052 VMXLOCAL_BREAK_RC(rc);
8053 }
8054
8055 if (fWhat & CPUMCTX_EXTRN_RSP)
8056 {
8057 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_RSP, &u64Val);
8058 VMXLOCAL_BREAK_RC(rc);
8059 pCtx->rsp = u64Val;
8060 }
8061
8062 if (fWhat & CPUMCTX_EXTRN_SREG_MASK)
8063 {
8064 bool const fRealOnV86Active = pVmcsInfo->RealMode.fRealOnV86Active;
8065 if (fWhat & CPUMCTX_EXTRN_CS)
8066 {
8067 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_CS);
8068 rc |= hmR0VmxImportGuestRip(pVCpu);
8069 if (fRealOnV86Active)
8070 pCtx->cs.Attr.u = pVmcsInfo->RealMode.AttrCS.u;
8071 EMR0HistoryUpdatePC(pVCpu, pCtx->cs.u64Base + pCtx->rip, true /* fFlattened */);
8072 }
8073 if (fWhat & CPUMCTX_EXTRN_SS)
8074 {
8075 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_SS);
8076 if (fRealOnV86Active)
8077 pCtx->ss.Attr.u = pVmcsInfo->RealMode.AttrSS.u;
8078 }
8079 if (fWhat & CPUMCTX_EXTRN_DS)
8080 {
8081 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_DS);
8082 if (fRealOnV86Active)
8083 pCtx->ds.Attr.u = pVmcsInfo->RealMode.AttrDS.u;
8084 }
8085 if (fWhat & CPUMCTX_EXTRN_ES)
8086 {
8087 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_ES);
8088 if (fRealOnV86Active)
8089 pCtx->es.Attr.u = pVmcsInfo->RealMode.AttrES.u;
8090 }
8091 if (fWhat & CPUMCTX_EXTRN_FS)
8092 {
8093 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_FS);
8094 if (fRealOnV86Active)
8095 pCtx->fs.Attr.u = pVmcsInfo->RealMode.AttrFS.u;
8096 }
8097 if (fWhat & CPUMCTX_EXTRN_GS)
8098 {
8099 rc |= hmR0VmxImportGuestSegReg(pVCpu, X86_SREG_GS);
8100 if (fRealOnV86Active)
8101 pCtx->gs.Attr.u = pVmcsInfo->RealMode.AttrGS.u;
8102 }
8103 VMXLOCAL_BREAK_RC(rc);
8104 }
8105
8106 if (fWhat & CPUMCTX_EXTRN_TABLE_MASK)
8107 {
8108 if (fWhat & CPUMCTX_EXTRN_LDTR)
8109 rc |= hmR0VmxImportGuestLdtr(pVCpu);
8110
8111 if (fWhat & CPUMCTX_EXTRN_GDTR)
8112 {
8113 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
8114 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
8115 pCtx->gdtr.pGdt = u64Val;
8116 pCtx->gdtr.cbGdt = u32Val;
8117 }
8118
8119 /* Guest IDTR. */
8120 if (fWhat & CPUMCTX_EXTRN_IDTR)
8121 {
8122 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
8123 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
8124 pCtx->idtr.pIdt = u64Val;
8125 pCtx->idtr.cbIdt = u32Val;
8126 }
8127
8128 /* Guest TR. */
8129 if (fWhat & CPUMCTX_EXTRN_TR)
8130 {
8131 /* Real-mode emulation using virtual-8086 mode has the fake TSS (pRealModeTSS) in TR,
8132 don't need to import that one. */
8133 if (!pVmcsInfo->RealMode.fRealOnV86Active)
8134 rc |= hmR0VmxImportGuestTr(pVCpu);
8135 }
8136 VMXLOCAL_BREAK_RC(rc);
8137 }
8138
8139 if (fWhat & CPUMCTX_EXTRN_DR7)
8140 {
8141 if (!pVCpu->hm.s.fUsingHyperDR7)
8142 {
8143 /* Upper 32-bits are always zero. See Intel spec. 2.7.3 "Loading and Storing Debug Registers". */
8144 rc = VMXReadVmcs32(VMX_VMCS_GUEST_DR7, &u32Val);
8145 VMXLOCAL_BREAK_RC(rc);
8146 pCtx->dr[7] = u32Val;
8147 }
8148 }
8149
8150 if (fWhat & CPUMCTX_EXTRN_SYSENTER_MSRS)
8151 {
8152 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_EIP, &pCtx->SysEnter.eip);
8153 rc |= VMXReadVmcsGstN(VMX_VMCS_GUEST_SYSENTER_ESP, &pCtx->SysEnter.esp);
8154 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_SYSENTER_CS, &u32Val);
8155 pCtx->SysEnter.cs = u32Val;
8156 VMXLOCAL_BREAK_RC(rc);
8157 }
8158
8159#if HC_ARCH_BITS == 64
8160 if (fWhat & CPUMCTX_EXTRN_KERNEL_GS_BASE)
8161 {
8162 if ( pVM->hm.s.fAllow64BitGuests
8163 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8164 pCtx->msrKERNELGSBASE = ASMRdMsr(MSR_K8_KERNEL_GS_BASE);
8165 }
8166
8167 if (fWhat & CPUMCTX_EXTRN_SYSCALL_MSRS)
8168 {
8169 if ( pVM->hm.s.fAllow64BitGuests
8170 && (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST))
8171 {
8172 pCtx->msrLSTAR = ASMRdMsr(MSR_K8_LSTAR);
8173 pCtx->msrSTAR = ASMRdMsr(MSR_K6_STAR);
8174 pCtx->msrSFMASK = ASMRdMsr(MSR_K8_SF_MASK);
8175 }
8176 }
8177#endif
8178
8179 if ( (fWhat & (CPUMCTX_EXTRN_TSC_AUX | CPUMCTX_EXTRN_OTHER_MSRS))
8180#if HC_ARCH_BITS == 32
8181 || (fWhat & (CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS))
8182#endif
8183 )
8184 {
8185 PCVMXAUTOMSR pMsrs = (PCVMXAUTOMSR)pVmcsInfo->pvGuestMsrStore;
8186 uint32_t const cMsrs = pVmcsInfo->cExitMsrStore;
8187 Assert(pMsrs);
8188 Assert(cMsrs <= VMX_MISC_MAX_MSRS(pVM->hm.s.vmx.Msrs.u64Misc));
8189 Assert(sizeof(*pMsrs) * cMsrs <= X86_PAGE_4K_SIZE);
8190 for (uint32_t i = 0; i < cMsrs; i++)
8191 {
8192 uint32_t const idMsr = pMsrs[i].u32Msr;
8193 switch (idMsr)
8194 {
8195 case MSR_K8_TSC_AUX: CPUMSetGuestTscAux(pVCpu, pMsrs[i].u64Value); break;
8196 case MSR_IA32_SPEC_CTRL: CPUMSetGuestSpecCtrl(pVCpu, pMsrs[i].u64Value); break;
8197 case MSR_K6_EFER: /* Can't be changed without causing a VM-exit */ break;
8198#if HC_ARCH_BITS == 32
8199 case MSR_K8_LSTAR: pCtx->msrLSTAR = pMsrs[i].u64Value; break;
8200 case MSR_K6_STAR: pCtx->msrSTAR = pMsrs[i].u64Value; break;
8201 case MSR_K8_SF_MASK: pCtx->msrSFMASK = pMsrs[i].u64Value; break;
8202 case MSR_K8_KERNEL_GS_BASE: pCtx->msrKERNELGSBASE = pMsrs[i].u64Value; break;
8203#endif
8204 default:
8205 {
8206 pCtx->fExtrn = 0;
8207 pVCpu->hm.s.u32HMError = pMsrs->u32Msr;
8208 ASMSetFlags(fEFlags);
8209 AssertMsgFailed(("Unexpected MSR in auto-load/store area. idMsr=%#RX32 cMsrs=%u\n", idMsr, cMsrs));
8210 return VERR_HM_UNEXPECTED_LD_ST_MSR;
8211 }
8212 }
8213 }
8214 }
8215
8216 if (fWhat & CPUMCTX_EXTRN_CR_MASK)
8217 {
8218 uint64_t u64Shadow;
8219 if (fWhat & CPUMCTX_EXTRN_CR0)
8220 {
8221 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8222 * remove when we drop 32-bit host w/ 64-bit host support, see
8223 * @bugref{9180#c39}. */
8224 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val);
8225#if HC_ARCH_BITS == 32
8226 uint32_t u32Shadow;
8227 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u32Shadow);
8228 u64Shadow = u32Shadow;
8229#else
8230 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR0_READ_SHADOW, &u64Shadow);
8231#endif
8232 VMXLOCAL_BREAK_RC(rc);
8233 u64Val = u32Val;
8234 u64Val = (u64Val & ~pVmcsInfo->u64Cr0Mask)
8235 | (u64Shadow & pVmcsInfo->u64Cr0Mask);
8236#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8237 /*
8238 * Reapply the nested-guest's CR0 fixed bits that might have been altered while
8239 * exporting the nested-guest CR0 for executing using hardware-assisted VMX.
8240 */
8241 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8242 {
8243 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed0;
8244 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr0Fixed1;
8245 }
8246#endif
8247 VMMRZCallRing3Disable(pVCpu); /* May call into PGM which has Log statements. */
8248 CPUMSetGuestCR0(pVCpu, u64Val);
8249 VMMRZCallRing3Enable(pVCpu);
8250 }
8251
8252 if (fWhat & CPUMCTX_EXTRN_CR4)
8253 {
8254 /** @todo r=ramshankar: We only read 32-bits here for legacy/convenience reasons,
8255 * remove when we drop 32-bit host w/ 64-bit host support, see
8256 * @bugref{9180#c39}. */
8257 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32Val);
8258#if HC_ARCH_BITS == 32
8259 uint32_t u32Shadow;
8260 rc |= VMXReadVmcs32(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u32Shadow);
8261 u64Shadow = u32Shadow;
8262#else
8263 rc |= VMXReadVmcs64(VMX_VMCS_CTRL_CR4_READ_SHADOW, &u64Shadow);
8264#endif
8265 VMXLOCAL_BREAK_RC(rc);
8266 u64Val = u32Val;
8267 u64Val = (u64Val & ~pVmcsInfo->u64Cr4Mask)
8268 | (u64Shadow & pVmcsInfo->u64Cr4Mask);
8269#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8270 /*
8271 * Reapply the nested-guest's CR4 fixed bits that might have been altered while
8272 * exporting the nested-guest CR4 for executing using hardware-assisted VMX.
8273 */
8274 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8275 {
8276 u64Val |= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed0;
8277 u64Val &= pCtx->hwvirt.vmx.Msrs.u64Cr4Fixed1;
8278 }
8279#endif
8280 pCtx->cr4 = u64Val;
8281 }
8282
8283 if (fWhat & CPUMCTX_EXTRN_CR3)
8284 {
8285 /* CR0.PG bit changes are always intercepted, so it's up to date. */
8286 if ( pVM->hm.s.vmx.fUnrestrictedGuest
8287 || ( pVM->hm.s.fNestedPaging
8288 && CPUMIsGuestPagingEnabledEx(pCtx)))
8289 {
8290 rc = VMXReadVmcsGstN(VMX_VMCS_GUEST_CR3, &u64Val);
8291 VMXLOCAL_BREAK_RC(rc);
8292 if (pCtx->cr3 != u64Val)
8293 {
8294 pCtx->cr3 = u64Val;
8295 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3);
8296 }
8297
8298 /* If the guest is in PAE mode, sync back the PDPE's into the guest state.
8299 Note: CR4.PAE, CR0.PG, EFER MSR changes are always intercepted, so they're up to date. */
8300 if (CPUMIsGuestInPAEModeEx(pCtx))
8301 {
8302 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &pVCpu->hm.s.aPdpes[0].u);
8303 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &pVCpu->hm.s.aPdpes[1].u);
8304 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &pVCpu->hm.s.aPdpes[2].u);
8305 rc |= VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &pVCpu->hm.s.aPdpes[3].u);
8306 VMXLOCAL_BREAK_RC(rc);
8307 VMCPU_FF_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES);
8308 }
8309 }
8310 }
8311 }
8312
8313#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8314 if (fWhat & CPUMCTX_EXTRN_HWVIRT)
8315 {
8316 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING)
8317 && !CPUMIsGuestInVmxNonRootMode(pCtx))
8318 {
8319 Assert(CPUMIsGuestInVmxRootMode(pCtx));
8320 rc = hmR0VmxCopyShadowToNstGstVmcs(pVCpu, pVmcsInfo);
8321 VMXLOCAL_BREAK_RC(rc);
8322 }
8323
8324# if 0
8325 /** @todo NSTVMX: We handle most of these fields individually by passing it to IEM
8326 * VM-exit handlers as parameters. We would handle it differently when using
8327 * the fast path. */
8328 /*
8329 * The hardware virtualization state currently consists of VMCS fields that may be
8330 * modified by execution of the nested-guest (that are not part of the general
8331 * guest state) and is visible to guest software. Hence, it is technically part of
8332 * the guest-CPU state when executing a nested-guest.
8333 */
8334 if (CPUMIsGuestInVmxNonRootMode(pCtx))
8335 {
8336 PVMXVVMCS pGstVmcs = pCtx->hwvirt.vmx.CTX_SUFF(pVmcs);
8337 rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &pGstVmcs->u32RoExitReason);
8338 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_EXIT_QUALIFICATION, &pGstVmcs->u64RoExitQual.u);
8339 VMXLOCAL_BREAK_RC(rc);
8340
8341 /*
8342 * VM-entry can fail due to invalid-guest state, machine-check events and
8343 * MSR loading failures. Other than VM-exit reason and Exit qualification
8344 * all other VMCS fields are left unmodified on VM-entry failure.
8345 *
8346 * See Intel spec. 26.7 "VM-entry Failures During Or After Loading Guest State".
8347 */
8348 bool const fEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(pGstVmcs->u32RoExitReason);
8349 if (!fEntryFailed)
8350 {
8351 /*
8352 * Some notes on VMCS fields that may need importing when the fast path
8353 * is implemented. Currently we fully emulate VMLAUNCH/VMRESUME in IEM.
8354 *
8355 * Requires fixing up when using hardware-assisted VMX:
8356 * - VM-exit interruption info: Shouldn't reflect host interrupts/NMIs.
8357 * - VM-exit interruption error code: Cleared to 0 when not appropriate.
8358 * - IDT-vectoring info: Think about this.
8359 * - IDT-vectoring error code: Think about this.
8360 *
8361 * Emulated:
8362 * - Guest-interruptiblity state: Derived from FFs and RIP.
8363 * - Guest pending debug exceptions: Derived from DR6.
8364 * - Guest activity state: Emulated from EM state.
8365 * - Guest PDPTEs: Currently all 0s since we don't support nested EPT.
8366 * - Entry-interrupt info: Emulated, cleared to 0.
8367 */
8368 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_INFO, &pGstVmcs->u32RoExitIntInfo);
8369 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INTERRUPTION_ERROR_CODE, &pGstVmcs->u32RoExitIntErrCode);
8370 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_INFO, &pGstVmcs->u32RoIdtVectoringInfo);
8371 rc |= VMXReadVmcs32(VMX_VMCS32_RO_IDT_VECTORING_ERROR_CODE, &pGstVmcs->u32RoIdtVectoringErrCode);
8372 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_LENGTH, &pGstVmcs->u32RoExitInstrLen);
8373 rc |= VMXReadVmcs32(VMX_VMCS32_RO_EXIT_INSTR_INFO, &pGstVmcs->u32RoExitIntInfo);
8374 rc |= VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &pGstVmcs->u64RoGuestPhysAddr.u);
8375 rc |= VMXReadVmcsGstN(VMX_VMCS_RO_GUEST_LINEAR_ADDR, &pGstVmcs->u64RoGuestLinearAddr.u);
8376 /** @todo NSTVMX: Save and adjust preemption timer value. */
8377 }
8378
8379 VMXLOCAL_BREAK_RC(rc);
8380 }
8381# endif
8382 }
8383#endif
8384 } while (0);
8385
8386 if (RT_SUCCESS(rc))
8387 {
8388 /* Update fExtrn. */
8389 pCtx->fExtrn &= ~fWhat;
8390
8391 /* If everything has been imported, clear the HM keeper bit. */
8392 if (!(pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL))
8393 {
8394 pCtx->fExtrn &= ~CPUMCTX_EXTRN_KEEPER_HM;
8395 Assert(!pCtx->fExtrn);
8396 }
8397 }
8398 }
8399 else
8400 AssertMsg(!pCtx->fExtrn || (pCtx->fExtrn & HMVMX_CPUMCTX_EXTRN_ALL), ("%#RX64\n", pCtx->fExtrn));
8401
8402 ASMSetFlags(fEFlags);
8403
8404 STAM_PROFILE_ADV_STOP(& pVCpu->hm.s.StatImportGuestState, x);
8405
8406 if (RT_SUCCESS(rc))
8407 { /* likely */ }
8408 else
8409 return rc;
8410
8411 /*
8412 * Honor any pending CR3 updates.
8413 *
8414 * Consider this scenario: VM-exit -> VMMRZCallRing3Enable() -> do stuff that causes a longjmp -> hmR0VmxCallRing3Callback()
8415 * -> VMMRZCallRing3Disable() -> hmR0VmxImportGuestState() -> Sets VMCPU_FF_HM_UPDATE_CR3 pending -> return from the longjmp
8416 * -> continue with VM-exit handling -> hmR0VmxImportGuestState() and here we are.
8417 *
8418 * The reason for such complicated handling is because VM-exits that call into PGM expect CR3 to be up-to-date and thus
8419 * if any CR3-saves -before- the VM-exit (longjmp) postponed the CR3 update via the force-flag, any VM-exit handler that
8420 * calls into PGM when it re-saves CR3 will end up here and we call PGMUpdateCR3(). This is why the code below should
8421 * -NOT- check if CPUMCTX_EXTRN_CR3 is set!
8422 *
8423 * The longjmp exit path can't check these CR3 force-flags and call code that takes a lock again. We cover for it here.
8424 */
8425 if (VMMRZCallRing3IsEnabled(pVCpu))
8426 {
8427 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
8428 {
8429 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_CR3));
8430 PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
8431 }
8432
8433 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
8434 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
8435
8436 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
8437 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
8438 }
8439
8440 return VINF_SUCCESS;
8441#undef VMXLOCAL_BREAK_RC
8442}
8443
8444
8445/**
8446 * Saves the guest state from the VMCS into the guest-CPU context.
8447 *
8448 * @returns VBox status code.
8449 * @param pVCpu The cross context virtual CPU structure.
8450 * @param fWhat What to import, CPUMCTX_EXTRN_XXX.
8451 */
8452VMMR0DECL(int) VMXR0ImportStateOnDemand(PVMCPU pVCpu, uint64_t fWhat)
8453{
8454 AssertPtr(pVCpu);
8455 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8456 return hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fWhat);
8457}
8458
8459
8460/**
8461 * Check per-VM and per-VCPU force flag actions that require us to go back to
8462 * ring-3 for one reason or another.
8463 *
8464 * @returns Strict VBox status code (i.e. informational status codes too)
8465 * @retval VINF_SUCCESS if we don't have any actions that require going back to
8466 * ring-3.
8467 * @retval VINF_PGM_SYNC_CR3 if we have pending PGM CR3 sync.
8468 * @retval VINF_EM_PENDING_REQUEST if we have pending requests (like hardware
8469 * interrupts)
8470 * @retval VINF_PGM_POOL_FLUSH_PENDING if PGM is doing a pool flush and requires
8471 * all EMTs to be in ring-3.
8472 * @retval VINF_EM_RAW_TO_R3 if there is pending DMA requests.
8473 * @retval VINF_EM_NO_MEMORY PGM is out of memory, we need to return
8474 * to the EM loop.
8475 *
8476 * @param pVCpu The cross context virtual CPU structure.
8477 * @param fStepping Whether we are single-stepping the guest using the
8478 * hypervisor debugger.
8479 */
8480static VBOXSTRICTRC hmR0VmxCheckForceFlags(PVMCPU pVCpu, bool fStepping)
8481{
8482 Assert(VMMRZCallRing3IsEnabled(pVCpu));
8483
8484 /*
8485 * Update pending interrupts into the APIC's IRR.
8486 */
8487 if (VMCPU_FF_TEST_AND_CLEAR(pVCpu, VMCPU_FF_UPDATE_APIC))
8488 APICUpdatePendingInterrupts(pVCpu);
8489
8490 /*
8491 * Anything pending? Should be more likely than not if we're doing a good job.
8492 */
8493 PVM pVM = pVCpu->CTX_SUFF(pVM);
8494 if ( !fStepping
8495 ? !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_MASK)
8496 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_MASK)
8497 : !VM_FF_IS_ANY_SET(pVM, VM_FF_HP_R0_PRE_HM_STEP_MASK)
8498 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HP_R0_PRE_HM_STEP_MASK) )
8499 return VINF_SUCCESS;
8500
8501 /* Pending PGM C3 sync. */
8502 if (VMCPU_FF_IS_ANY_SET(pVCpu,VMCPU_FF_PGM_SYNC_CR3 | VMCPU_FF_PGM_SYNC_CR3_NON_GLOBAL))
8503 {
8504 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
8505 Assert(!(ASMAtomicUoReadU64(&pCtx->fExtrn) & (CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4)));
8506 VBOXSTRICTRC rcStrict2 = PGMSyncCR3(pVCpu, pCtx->cr0, pCtx->cr3, pCtx->cr4,
8507 VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
8508 if (rcStrict2 != VINF_SUCCESS)
8509 {
8510 AssertRC(VBOXSTRICTRC_VAL(rcStrict2));
8511 Log4Func(("PGMSyncCR3 forcing us back to ring-3. rc2=%d\n", VBOXSTRICTRC_VAL(rcStrict2)));
8512 return rcStrict2;
8513 }
8514 }
8515
8516 /* Pending HM-to-R3 operations (critsects, timers, EMT rendezvous etc.) */
8517 if ( VM_FF_IS_ANY_SET(pVM, VM_FF_HM_TO_R3_MASK)
8518 || VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
8519 {
8520 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
8521 int rc2 = RT_LIKELY(!VM_FF_IS_SET(pVM, VM_FF_PGM_NO_MEMORY)) ? VINF_EM_RAW_TO_R3 : VINF_EM_NO_MEMORY;
8522 Log4Func(("HM_TO_R3 forcing us back to ring-3. rc=%d\n", rc2));
8523 return rc2;
8524 }
8525
8526 /* Pending VM request packets, such as hardware interrupts. */
8527 if ( VM_FF_IS_SET(pVM, VM_FF_REQUEST)
8528 || VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_REQUEST))
8529 {
8530 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchVmReq);
8531 Log4Func(("Pending VM request forcing us back to ring-3\n"));
8532 return VINF_EM_PENDING_REQUEST;
8533 }
8534
8535 /* Pending PGM pool flushes. */
8536 if (VM_FF_IS_SET(pVM, VM_FF_PGM_POOL_FLUSH_PENDING))
8537 {
8538 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPgmPoolFlush);
8539 Log4Func(("PGM pool flush pending forcing us back to ring-3\n"));
8540 return VINF_PGM_POOL_FLUSH_PENDING;
8541 }
8542
8543 /* Pending DMA requests. */
8544 if (VM_FF_IS_SET(pVM, VM_FF_PDM_DMA))
8545 {
8546 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchDma);
8547 Log4Func(("Pending DMA request forcing us back to ring-3\n"));
8548 return VINF_EM_RAW_TO_R3;
8549 }
8550
8551 return VINF_SUCCESS;
8552}
8553
8554
8555/**
8556 * Converts any TRPM trap into a pending HM event. This is typically used when
8557 * entering from ring-3 (not longjmp returns).
8558 *
8559 * @param pVCpu The cross context virtual CPU structure.
8560 */
8561static void hmR0VmxTrpmTrapToPendingEvent(PVMCPU pVCpu)
8562{
8563 Assert(TRPMHasTrap(pVCpu));
8564 Assert(!pVCpu->hm.s.Event.fPending);
8565
8566 uint8_t uVector;
8567 TRPMEVENT enmTrpmEvent;
8568 RTGCUINT uErrCode;
8569 RTGCUINTPTR GCPtrFaultAddress;
8570 uint8_t cbInstr;
8571
8572 int rc = TRPMQueryTrapAll(pVCpu, &uVector, &enmTrpmEvent, &uErrCode, &GCPtrFaultAddress, &cbInstr);
8573 AssertRC(rc);
8574
8575 uint32_t u32IntInfo;
8576 u32IntInfo = uVector | VMX_IDT_VECTORING_INFO_VALID;
8577 u32IntInfo |= HMTrpmEventTypeToVmxEventType(uVector, enmTrpmEvent);
8578
8579 rc = TRPMResetTrap(pVCpu);
8580 AssertRC(rc);
8581 Log4(("TRPM->HM event: u32IntInfo=%#RX32 enmTrpmEvent=%d cbInstr=%u uErrCode=%#RX32 GCPtrFaultAddress=%#RGv\n",
8582 u32IntInfo, enmTrpmEvent, cbInstr, uErrCode, GCPtrFaultAddress));
8583
8584 hmR0VmxSetPendingEvent(pVCpu, u32IntInfo, cbInstr, uErrCode, GCPtrFaultAddress);
8585}
8586
8587
8588/**
8589 * Converts the pending HM event into a TRPM trap.
8590 *
8591 * @param pVCpu The cross context virtual CPU structure.
8592 */
8593static void hmR0VmxPendingEventToTrpmTrap(PVMCPU pVCpu)
8594{
8595 Assert(pVCpu->hm.s.Event.fPending);
8596
8597 /* If a trap was already pending, we did something wrong! */
8598 Assert(TRPMQueryTrap(pVCpu, NULL /* pu8TrapNo */, NULL /* pEnmType */) == VERR_TRPM_NO_ACTIVE_TRAP);
8599
8600 uint32_t const u32IntInfo = pVCpu->hm.s.Event.u64IntInfo;
8601 uint32_t const uVector = VMX_IDT_VECTORING_INFO_VECTOR(u32IntInfo);
8602 TRPMEVENT const enmTrapType = HMVmxEventTypeToTrpmEventType(u32IntInfo);
8603
8604 Log4(("HM event->TRPM: uVector=%#x enmTrapType=%d\n", uVector, enmTrapType));
8605
8606 int rc = TRPMAssertTrap(pVCpu, uVector, enmTrapType);
8607 AssertRC(rc);
8608
8609 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
8610 TRPMSetErrorCode(pVCpu, pVCpu->hm.s.Event.u32ErrCode);
8611
8612 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(u32IntInfo))
8613 TRPMSetFaultAddress(pVCpu, pVCpu->hm.s.Event.GCPtrFaultAddress);
8614 else if (VMX_IDT_VECTORING_INFO_TYPE(u32IntInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT)
8615 TRPMSetInstrLength(pVCpu, pVCpu->hm.s.Event.cbInstr);
8616
8617 /* We're now done converting the pending event. */
8618 pVCpu->hm.s.Event.fPending = false;
8619}
8620
8621
8622/**
8623 * Sets the interrupt-window exiting control in the VMCS which instructs VT-x to
8624 * cause a VM-exit as soon as the guest is in a state to receive interrupts.
8625 *
8626 * @param pVCpu The cross context virtual CPU structure.
8627 * @param pVmcsInfo The VMCS info. object.
8628 */
8629static void hmR0VmxSetIntWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8630{
8631 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8632 {
8633 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT))
8634 {
8635 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_INT_WINDOW_EXIT;
8636 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8637 AssertRC(rc);
8638 }
8639 } /* else we will deliver interrupts whenever the guest Vm-exits next and is in a state to receive the interrupt. */
8640}
8641
8642
8643/**
8644 * Clears the interrupt-window exiting control in the VMCS.
8645 *
8646 * @param pVmcsInfo The VMCS info. object.
8647 */
8648DECLINLINE(int) hmR0VmxClearIntWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8649{
8650 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_INT_WINDOW_EXIT)
8651 {
8652 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_INT_WINDOW_EXIT;
8653 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8654 }
8655 return VINF_SUCCESS;
8656}
8657
8658
8659/**
8660 * Sets the NMI-window exiting control in the VMCS which instructs VT-x to
8661 * cause a VM-exit as soon as the guest is in a state to receive NMIs.
8662 *
8663 * @param pVCpu The cross context virtual CPU structure.
8664 * @param pVmcsInfo The VMCS info. object.
8665 */
8666static void hmR0VmxSetNmiWindowExitVmcs(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo)
8667{
8668 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8669 {
8670 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))
8671 {
8672 pVmcsInfo->u32ProcCtls |= VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8673 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8674 AssertRC(rc);
8675 Log4Func(("Setup NMI-window exiting\n"));
8676 }
8677 } /* else we will deliver NMIs whenever we VM-exit next, even possibly nesting NMIs. Can't be helped on ancient CPUs. */
8678}
8679
8680
8681/**
8682 * Clears the NMI-window exiting control in the VMCS.
8683 *
8684 * @param pVmcsInfo The VMCS info. object.
8685 */
8686DECLINLINE(int) hmR0VmxClearNmiWindowExitVmcs(PVMXVMCSINFO pVmcsInfo)
8687{
8688 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT)
8689 {
8690 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_NMI_WINDOW_EXIT;
8691 return VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
8692 }
8693 return VINF_SUCCESS;
8694}
8695
8696
8697/**
8698 * Does the necessary state syncing before returning to ring-3 for any reason
8699 * (longjmp, preemption, voluntary exits to ring-3) from VT-x.
8700 *
8701 * @returns VBox status code.
8702 * @param pVCpu The cross context virtual CPU structure.
8703 * @param fImportState Whether to import the guest state from the VMCS back
8704 * to the guest-CPU context.
8705 *
8706 * @remarks No-long-jmp zone!!!
8707 */
8708static int hmR0VmxLeave(PVMCPU pVCpu, bool fImportState)
8709{
8710 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8711 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8712
8713 RTCPUID const idCpu = RTMpCpuId();
8714 Log4Func(("HostCpuId=%u\n", idCpu));
8715
8716 /*
8717 * !!! IMPORTANT !!!
8718 * If you modify code here, check whether hmR0VmxCallRing3Callback() needs to be updated too.
8719 */
8720
8721 /* Save the guest state if necessary. */
8722 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8723 if (fImportState)
8724 {
8725 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
8726 AssertRCReturn(rc, rc);
8727 }
8728
8729 /* Restore host FPU state if necessary. We will resync on next R0 reentry. */
8730 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
8731 Assert(!CPUMIsGuestFPUStateActive(pVCpu));
8732
8733 /* Restore host debug registers if necessary. We will resync on next R0 reentry. */
8734#ifdef VBOX_STRICT
8735 if (CPUMIsHyperDebugStateActive(pVCpu))
8736 Assert(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_MOV_DR_EXIT);
8737#endif
8738 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
8739 Assert(!CPUMIsGuestDebugStateActive(pVCpu) && !CPUMIsGuestDebugStateActivePending(pVCpu));
8740 Assert(!CPUMIsHyperDebugStateActive(pVCpu) && !CPUMIsHyperDebugStateActivePending(pVCpu));
8741
8742#if HC_ARCH_BITS == 64
8743 /* Restore host-state bits that VT-x only restores partially. */
8744 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
8745 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
8746 {
8747 Log4Func(("Restoring Host State: fRestoreHostFlags=%#RX32 HostCpuId=%u\n", pVCpu->hm.s.vmx.fRestoreHostFlags, idCpu));
8748 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
8749 }
8750 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
8751#endif
8752
8753 /* Restore the lazy host MSRs as we're leaving VT-x context. */
8754 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
8755 {
8756 /* We shouldn't restore the host MSRs without saving the guest MSRs first. */
8757 if (!fImportState)
8758 {
8759 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_KERNEL_GS_BASE | CPUMCTX_EXTRN_SYSCALL_MSRS);
8760 AssertRCReturn(rc, rc);
8761 }
8762 hmR0VmxLazyRestoreHostMsrs(pVCpu);
8763 Assert(!pVCpu->hm.s.vmx.fLazyMsrs);
8764 }
8765 else
8766 pVCpu->hm.s.vmx.fLazyMsrs = 0;
8767
8768 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
8769 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
8770
8771 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatEntry);
8772 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatImportGuestState);
8773 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExportGuestState);
8774 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatPreExit);
8775 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitHandling);
8776 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitIO);
8777 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitMovCRx);
8778 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitXcptNmi);
8779 STAM_PROFILE_ADV_SET_STOPPED(&pVCpu->hm.s.StatExitVmentry);
8780 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8781
8782 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
8783
8784 /** @todo This partially defeats the purpose of having preemption hooks.
8785 * The problem is, deregistering the hooks should be moved to a place that
8786 * lasts until the EMT is about to be destroyed not everytime while leaving HM
8787 * context.
8788 */
8789 int rc = hmR0VmxClearVmcs(pVmcsInfo);
8790 AssertRCReturn(rc, rc);
8791
8792#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
8793 /*
8794 * A valid shadow VMCS is made active as part of VM-entry. It is necessary to
8795 * clear a shadow VMCS before allowing that VMCS to become active on another
8796 * logical processor. We may or may not be importing guest state which clears
8797 * it, so cover for it here.
8798 *
8799 * See Intel spec. 24.11.1 "Software Use of Virtual-Machine Control Structures".
8800 */
8801 if ( pVmcsInfo->pvShadowVmcs
8802 && pVmcsInfo->fShadowVmcsState != VMX_V_VMCS_LAUNCH_STATE_CLEAR)
8803 {
8804 rc = hmR0VmxClearShadowVmcs(pVmcsInfo);
8805 AssertRCReturn(rc, rc);
8806 }
8807
8808 /*
8809 * Flag that we need to re-import the host state if we switch to this VMCS before
8810 * executing guest or nested-guest code.
8811 */
8812 pVmcsInfo->idHostCpu = NIL_RTCPUID;
8813#endif
8814
8815 Log4Func(("Cleared Vmcs. HostCpuId=%u\n", idCpu));
8816 NOREF(idCpu);
8817 return VINF_SUCCESS;
8818}
8819
8820
8821/**
8822 * Leaves the VT-x session.
8823 *
8824 * @returns VBox status code.
8825 * @param pVCpu The cross context virtual CPU structure.
8826 *
8827 * @remarks No-long-jmp zone!!!
8828 */
8829static int hmR0VmxLeaveSession(PVMCPU pVCpu)
8830{
8831 HM_DISABLE_PREEMPT(pVCpu);
8832 HMVMX_ASSERT_CPU_SAFE(pVCpu);
8833 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
8834 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
8835
8836 /* When thread-context hooks are used, we can avoid doing the leave again if we had been preempted before
8837 and done this from the VMXR0ThreadCtxCallback(). */
8838 if (!pVCpu->hm.s.fLeaveDone)
8839 {
8840 int rc2 = hmR0VmxLeave(pVCpu, true /* fImportState */);
8841 AssertRCReturnStmt(rc2, HM_RESTORE_PREEMPT(), rc2);
8842 pVCpu->hm.s.fLeaveDone = true;
8843 }
8844 Assert(!pVCpu->cpum.GstCtx.fExtrn);
8845
8846 /*
8847 * !!! IMPORTANT !!!
8848 * If you modify code here, make sure to check whether hmR0VmxCallRing3Callback() needs to be updated too.
8849 */
8850
8851 /* Deregister hook now that we've left HM context before re-enabling preemption. */
8852 /** @todo Deregistering here means we need to VMCLEAR always
8853 * (longjmp/exit-to-r3) in VT-x which is not efficient, eliminate need
8854 * for calling VMMR0ThreadCtxHookDisable here! */
8855 VMMR0ThreadCtxHookDisable(pVCpu);
8856
8857 /* Leave HM context. This takes care of local init (term). */
8858 int rc = HMR0LeaveCpu(pVCpu);
8859
8860 HM_RESTORE_PREEMPT();
8861 return rc;
8862}
8863
8864
8865/**
8866 * Does the necessary state syncing before doing a longjmp to ring-3.
8867 *
8868 * @returns VBox status code.
8869 * @param pVCpu The cross context virtual CPU structure.
8870 *
8871 * @remarks No-long-jmp zone!!!
8872 */
8873DECLINLINE(int) hmR0VmxLongJmpToRing3(PVMCPU pVCpu)
8874{
8875 return hmR0VmxLeaveSession(pVCpu);
8876}
8877
8878
8879/**
8880 * Take necessary actions before going back to ring-3.
8881 *
8882 * An action requires us to go back to ring-3. This function does the necessary
8883 * steps before we can safely return to ring-3. This is not the same as longjmps
8884 * to ring-3, this is voluntary and prepares the guest so it may continue
8885 * executing outside HM (recompiler/IEM).
8886 *
8887 * @returns VBox status code.
8888 * @param pVCpu The cross context virtual CPU structure.
8889 * @param rcExit The reason for exiting to ring-3. Can be
8890 * VINF_VMM_UNKNOWN_RING3_CALL.
8891 */
8892static int hmR0VmxExitToRing3(PVMCPU pVCpu, VBOXSTRICTRC rcExit)
8893{
8894 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
8895
8896 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
8897 if (RT_UNLIKELY(rcExit == VERR_VMX_INVALID_VMCS_PTR))
8898 {
8899 VMXGetCurrentVmcs(&pVCpu->hm.s.vmx.LastError.HCPhysCurrentVmcs);
8900 pVCpu->hm.s.vmx.LastError.u32VmcsRev = *(uint32_t *)pVmcsInfo->pvVmcs;
8901 pVCpu->hm.s.vmx.LastError.idEnteredCpu = pVCpu->hm.s.idEnteredCpu;
8902 /* LastError.idCurrentCpu was updated in hmR0VmxPreRunGuestCommitted(). */
8903 }
8904
8905 /* Please, no longjumps here (any logging shouldn't flush jump back to ring-3). NO LOGGING BEFORE THIS POINT! */
8906 VMMRZCallRing3Disable(pVCpu);
8907 Log4Func(("rcExit=%d\n", VBOXSTRICTRC_VAL(rcExit)));
8908
8909 /*
8910 * Convert any pending HM events back to TRPM due to premature exits to ring-3.
8911 * We need to do this only on returns to ring-3 and not for longjmps to ring3.
8912 *
8913 * This is because execution may continue from ring-3 and we would need to inject
8914 * the event from there (hence place it back in TRPM).
8915 */
8916 if (pVCpu->hm.s.Event.fPending)
8917 {
8918 hmR0VmxPendingEventToTrpmTrap(pVCpu);
8919 Assert(!pVCpu->hm.s.Event.fPending);
8920
8921 /* Clear the events from the VMCS. */
8922 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, 0);
8923 AssertRCReturn(rc, rc);
8924 }
8925#ifdef VBOX_STRICT
8926 else
8927 {
8928 /*
8929 * Ensure we don't accidentally clear a pending HM event without clearing the VMCS.
8930 * This can be pretty hard to debug otherwise, interrupts might get injected twice
8931 * occasionally, see @bugref{9180#c42}.
8932 *
8933 * However, if the VM-entry failed, any VM entry-interruption info. field would
8934 * be left unmodified as the event would not have been injected to the guest. In
8935 * such cases, don't assert, we're not going to continue guest execution anyway.
8936 */
8937 uint32_t uExitReason;
8938 uint32_t uEntryIntInfo;
8939 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
8940 rc |= VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &uEntryIntInfo);
8941 AssertRC(rc);
8942 Assert(VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason) || !VMX_ENTRY_INT_INFO_IS_VALID(uEntryIntInfo));
8943 }
8944#endif
8945
8946 /*
8947 * Clear the interrupt-window and NMI-window VMCS controls as we could have got
8948 * a VM-exit with higher priority than interrupt-window or NMI-window VM-exits
8949 * (e.g. TPR below threshold).
8950 */
8951 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8952 {
8953 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
8954 rc |= hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
8955 AssertRCReturn(rc, rc);
8956 }
8957
8958 /* If we're emulating an instruction, we shouldn't have any TRPM traps pending
8959 and if we're injecting an event we should have a TRPM trap pending. */
8960 AssertMsg(rcExit != VINF_EM_RAW_INJECT_TRPM_EVENT || TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8961#ifndef DEBUG_bird /* Triggered after firing an NMI against NT4SP1, possibly a triple fault in progress. */
8962 AssertMsg(rcExit != VINF_EM_RAW_EMULATE_INSTR || !TRPMHasTrap(pVCpu), ("%Rrc\n", VBOXSTRICTRC_VAL(rcExit)));
8963#endif
8964
8965 /* Save guest state and restore host state bits. */
8966 int rc = hmR0VmxLeaveSession(pVCpu);
8967 AssertRCReturn(rc, rc);
8968 STAM_COUNTER_DEC(&pVCpu->hm.s.StatSwitchLongJmpToR3);
8969
8970 /* Thread-context hooks are unregistered at this point!!! */
8971
8972 /* Sync recompiler state. */
8973 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TO_R3);
8974 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_SYSENTER_MSR
8975 | CPUM_CHANGED_LDTR
8976 | CPUM_CHANGED_GDTR
8977 | CPUM_CHANGED_IDTR
8978 | CPUM_CHANGED_TR
8979 | CPUM_CHANGED_HIDDEN_SEL_REGS);
8980 if ( pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging
8981 && CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx))
8982 CPUMSetChangedFlags(pVCpu, CPUM_CHANGED_GLOBAL_TLB_FLUSH);
8983
8984 Assert(!pVCpu->hm.s.fClearTrapFlag);
8985
8986 /* Update the exit-to-ring 3 reason. */
8987 pVCpu->hm.s.rcLastExitToR3 = VBOXSTRICTRC_VAL(rcExit);
8988
8989 /* On our way back from ring-3 reload the guest state if there is a possibility of it being changed. */
8990 if ( rcExit != VINF_EM_RAW_INTERRUPT
8991 || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
8992 {
8993 Assert(!(pVCpu->cpum.GstCtx.fExtrn & HMVMX_CPUMCTX_EXTRN_ALL));
8994 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
8995 }
8996
8997 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchExitToR3);
8998
8999 /* We do -not- want any longjmp notifications after this! We must return to ring-3 ASAP. */
9000 VMMRZCallRing3RemoveNotification(pVCpu);
9001 VMMRZCallRing3Enable(pVCpu);
9002
9003 return rc;
9004}
9005
9006
9007/**
9008 * VMMRZCallRing3() callback wrapper which saves the guest state before we
9009 * longjump to ring-3 and possibly get preempted.
9010 *
9011 * @returns VBox status code.
9012 * @param pVCpu The cross context virtual CPU structure.
9013 * @param enmOperation The operation causing the ring-3 longjump.
9014 * @param pvUser User argument, currently unused, NULL.
9015 */
9016static DECLCALLBACK(int) hmR0VmxCallRing3Callback(PVMCPU pVCpu, VMMCALLRING3 enmOperation, void *pvUser)
9017{
9018 RT_NOREF(pvUser);
9019 if (enmOperation == VMMCALLRING3_VM_R0_ASSERTION)
9020 {
9021 /*
9022 * !!! IMPORTANT !!!
9023 * If you modify code here, check whether hmR0VmxLeave() and hmR0VmxLeaveSession() needs to be updated too.
9024 * This is a stripped down version which gets out ASAP, trying to not trigger any further assertions.
9025 */
9026 VMMRZCallRing3RemoveNotification(pVCpu);
9027 VMMRZCallRing3Disable(pVCpu);
9028 RTTHREADPREEMPTSTATE PreemptState = RTTHREADPREEMPTSTATE_INITIALIZER;
9029 RTThreadPreemptDisable(&PreemptState);
9030
9031 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9032 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
9033 CPUMR0FpuStateMaybeSaveGuestAndRestoreHost(pVCpu);
9034 CPUMR0DebugStateMaybeSaveGuestAndRestoreHost(pVCpu, true /* save DR6 */);
9035
9036#if HC_ARCH_BITS == 64
9037 /* Restore host-state bits that VT-x only restores partially. */
9038 if ( (pVCpu->hm.s.vmx.fRestoreHostFlags & VMX_RESTORE_HOST_REQUIRED)
9039 && (pVCpu->hm.s.vmx.fRestoreHostFlags & ~VMX_RESTORE_HOST_REQUIRED))
9040 VMXRestoreHostState(pVCpu->hm.s.vmx.fRestoreHostFlags, &pVCpu->hm.s.vmx.RestoreHost);
9041 pVCpu->hm.s.vmx.fRestoreHostFlags = 0;
9042#endif
9043
9044 /* Restore the lazy host MSRs as we're leaving VT-x context. */
9045 if (pVCpu->hm.s.vmx.fLazyMsrs & VMX_LAZY_MSRS_LOADED_GUEST)
9046 hmR0VmxLazyRestoreHostMsrs(pVCpu);
9047
9048 /* Update auto-load/store host MSRs values when we re-enter VT-x (as we could be on a different CPU). */
9049 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = false;
9050 VMCPU_CMPXCHG_STATE(pVCpu, VMCPUSTATE_STARTED_HM, VMCPUSTATE_STARTED_EXEC);
9051
9052 /* Clear the current VMCS data back to memory (shadow VMCS if any would have been
9053 cleared as part of importing the guest state above. */
9054 hmR0VmxClearVmcs(pVmcsInfo);
9055
9056 /** @todo eliminate the need for calling VMMR0ThreadCtxHookDisable here! */
9057 VMMR0ThreadCtxHookDisable(pVCpu);
9058 HMR0LeaveCpu(pVCpu);
9059 RTThreadPreemptRestore(&PreemptState);
9060 return VINF_SUCCESS;
9061 }
9062
9063 Assert(pVCpu);
9064 Assert(pvUser);
9065 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9066 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9067
9068 VMMRZCallRing3Disable(pVCpu);
9069 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9070
9071 Log4Func((" -> hmR0VmxLongJmpToRing3 enmOperation=%d\n", enmOperation));
9072
9073 int rc = hmR0VmxLongJmpToRing3(pVCpu);
9074 AssertRCReturn(rc, rc);
9075
9076 VMMRZCallRing3Enable(pVCpu);
9077 return VINF_SUCCESS;
9078}
9079
9080
9081/**
9082 * Pushes a 2-byte value onto the real-mode (in virtual-8086 mode) guest's
9083 * stack.
9084 *
9085 * @returns Strict VBox status code (i.e. informational status codes too).
9086 * @retval VINF_EM_RESET if pushing a value to the stack caused a triple-fault.
9087 * @param pVCpu The cross context virtual CPU structure.
9088 * @param uValue The value to push to the guest stack.
9089 */
9090static VBOXSTRICTRC hmR0VmxRealModeGuestStackPush(PVMCPU pVCpu, uint16_t uValue)
9091{
9092 /*
9093 * The stack limit is 0xffff in real-on-virtual 8086 mode. Real-mode with weird stack limits cannot be run in
9094 * virtual 8086 mode in VT-x. See Intel spec. 26.3.1.2 "Checks on Guest Segment Registers".
9095 * See Intel Instruction reference for PUSH and Intel spec. 22.33.1 "Segment Wraparound".
9096 */
9097 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9098 if (pCtx->sp == 1)
9099 return VINF_EM_RESET;
9100 pCtx->sp -= sizeof(uint16_t); /* May wrap around which is expected behaviour. */
9101 int rc = PGMPhysSimpleWriteGCPhys(pVCpu->CTX_SUFF(pVM), pCtx->ss.u64Base + pCtx->sp, &uValue, sizeof(uint16_t));
9102 AssertRC(rc);
9103 return rc;
9104}
9105
9106
9107/**
9108 * Injects an event into the guest upon VM-entry by updating the relevant fields
9109 * in the VM-entry area in the VMCS.
9110 *
9111 * @returns Strict VBox status code (i.e. informational status codes too).
9112 * @retval VINF_SUCCESS if the event is successfully injected into the VMCS.
9113 * @retval VINF_EM_RESET if event injection resulted in a triple-fault.
9114 *
9115 * @param pVCpu The cross context virtual CPU structure.
9116 * @param pVmxTransient The VMX-transient structure.
9117 * @param pEvent The event being injected.
9118 * @param pfIntrState Pointer to the VT-x guest-interruptibility-state. This
9119 * will be updated if necessary. This cannot not be NULL.
9120 * @param fStepping Whether we're single-stepping guest execution and should
9121 * return VINF_EM_DBG_STEPPED if the event is injected
9122 * directly (registers modified by us, not by hardware on
9123 * VM-entry).
9124 */
9125static VBOXSTRICTRC hmR0VmxInjectEventVmcs(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCHMEVENT pEvent, bool fStepping,
9126 uint32_t *pfIntrState)
9127{
9128 /* Intel spec. 24.8.3 "VM-Entry Controls for Event Injection" specifies the interruption-information field to be 32-bits. */
9129 AssertMsg(!RT_HI_U32(pEvent->u64IntInfo), ("%#RX64\n", pEvent->u64IntInfo));
9130 Assert(pfIntrState);
9131
9132 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9133 uint32_t u32IntInfo = pEvent->u64IntInfo;
9134 uint32_t const u32ErrCode = pEvent->u32ErrCode;
9135 uint32_t const cbInstr = pEvent->cbInstr;
9136 RTGCUINTPTR const GCPtrFault = pEvent->GCPtrFaultAddress;
9137 uint8_t const uVector = VMX_ENTRY_INT_INFO_VECTOR(u32IntInfo);
9138 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(u32IntInfo);
9139
9140#ifdef VBOX_STRICT
9141 /*
9142 * Validate the error-code-valid bit for hardware exceptions.
9143 * No error codes for exceptions in real-mode.
9144 *
9145 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9146 */
9147 if ( uIntType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT
9148 && !CPUMIsGuestInRealModeEx(pCtx))
9149 {
9150 switch (uVector)
9151 {
9152 case X86_XCPT_PF:
9153 case X86_XCPT_DF:
9154 case X86_XCPT_TS:
9155 case X86_XCPT_NP:
9156 case X86_XCPT_SS:
9157 case X86_XCPT_GP:
9158 case X86_XCPT_AC:
9159 AssertMsg(VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo),
9160 ("Error-code-valid bit not set for exception that has an error code uVector=%#x\n", uVector));
9161 RT_FALL_THRU();
9162 default:
9163 break;
9164 }
9165 }
9166
9167 /* Cannot inject an NMI when block-by-MOV SS is in effect. */
9168 Assert( uIntType != VMX_EXIT_INT_INFO_TYPE_NMI
9169 || !(*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
9170#endif
9171
9172 STAM_COUNTER_INC(&pVCpu->hm.s.paStatInjectedIrqsR0[uVector & MASK_INJECT_IRQ_STAT]);
9173
9174 /*
9175 * Hardware interrupts & exceptions cannot be delivered through the software interrupt
9176 * redirection bitmap to the real mode task in virtual-8086 mode. We must jump to the
9177 * interrupt handler in the (real-mode) guest.
9178 *
9179 * See Intel spec. 20.3 "Interrupt and Exception handling in Virtual-8086 Mode".
9180 * See Intel spec. 20.1.4 "Interrupt and Exception Handling" for real-mode interrupt handling.
9181 */
9182 if (CPUMIsGuestInRealModeEx(pCtx)) /* CR0.PE bit changes are always intercepted, so it's up to date. */
9183 {
9184 if (pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest)
9185 {
9186 /*
9187 * For CPUs with unrestricted guest execution enabled and with the guest
9188 * in real-mode, we must not set the deliver-error-code bit.
9189 *
9190 * See Intel spec. 26.2.1.3 "VM-Entry Control Fields".
9191 */
9192 u32IntInfo &= ~VMX_ENTRY_INT_INFO_ERROR_CODE_VALID;
9193 }
9194 else
9195 {
9196 PVM pVM = pVCpu->CTX_SUFF(pVM);
9197 Assert(PDMVmmDevHeapIsEnabled(pVM));
9198 Assert(pVM->hm.s.vmx.pRealModeTSS);
9199 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
9200
9201 /* We require RIP, RSP, RFLAGS, CS, IDTR, import them. */
9202 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9203 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_TABLE_MASK
9204 | CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_RFLAGS);
9205 AssertRCReturn(rc2, rc2);
9206
9207 /* Check if the interrupt handler is present in the IVT (real-mode IDT). IDT limit is (4N - 1). */
9208 size_t const cbIdtEntry = sizeof(X86IDTR16);
9209 if (uVector * cbIdtEntry + (cbIdtEntry - 1) > pCtx->idtr.cbIdt)
9210 {
9211 /* If we are trying to inject a #DF with no valid IDT entry, return a triple-fault. */
9212 if (uVector == X86_XCPT_DF)
9213 return VINF_EM_RESET;
9214
9215 /* If we're injecting a #GP with no valid IDT entry, inject a double-fault.
9216 No error codes for exceptions in real-mode. */
9217 if (uVector == X86_XCPT_GP)
9218 {
9219 uint32_t const uXcptDfInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_DF)
9220 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9221 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9222 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9223 HMEVENT EventXcptDf;
9224 RT_ZERO(EventXcptDf);
9225 EventXcptDf.u64IntInfo = uXcptDfInfo;
9226 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptDf, fStepping, pfIntrState);
9227 }
9228
9229 /*
9230 * If we're injecting an event with no valid IDT entry, inject a #GP.
9231 * No error codes for exceptions in real-mode.
9232 *
9233 * See Intel spec. 20.1.4 "Interrupt and Exception Handling"
9234 */
9235 uint32_t const uXcptGpInfo = RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VECTOR, X86_XCPT_GP)
9236 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_TYPE, VMX_ENTRY_INT_INFO_TYPE_HW_XCPT)
9237 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_ERR_CODE_VALID, 0)
9238 | RT_BF_MAKE(VMX_BF_ENTRY_INT_INFO_VALID, 1);
9239 HMEVENT EventXcptGp;
9240 RT_ZERO(EventXcptGp);
9241 EventXcptGp.u64IntInfo = uXcptGpInfo;
9242 return hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &EventXcptGp, fStepping, pfIntrState);
9243 }
9244
9245 /* Software exceptions (#BP and #OF exceptions thrown as a result of INT3 or INTO) */
9246 uint16_t uGuestIp = pCtx->ip;
9247 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_XCPT)
9248 {
9249 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF);
9250 /* #BP and #OF are both benign traps, we need to resume the next instruction. */
9251 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9252 }
9253 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_SW_INT)
9254 uGuestIp = pCtx->ip + (uint16_t)cbInstr;
9255
9256 /* Get the code segment selector and offset from the IDT entry for the interrupt handler. */
9257 X86IDTR16 IdtEntry;
9258 RTGCPHYS const GCPhysIdtEntry = (RTGCPHYS)pCtx->idtr.pIdt + uVector * cbIdtEntry;
9259 rc2 = PGMPhysSimpleReadGCPhys(pVM, &IdtEntry, GCPhysIdtEntry, cbIdtEntry);
9260 AssertRCReturn(rc2, rc2);
9261
9262 /* Construct the stack frame for the interrupt/exception handler. */
9263 VBOXSTRICTRC rcStrict;
9264 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->eflags.u32);
9265 if (rcStrict == VINF_SUCCESS)
9266 {
9267 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, pCtx->cs.Sel);
9268 if (rcStrict == VINF_SUCCESS)
9269 rcStrict = hmR0VmxRealModeGuestStackPush(pVCpu, uGuestIp);
9270 }
9271
9272 /* Clear the required eflag bits and jump to the interrupt/exception handler. */
9273 if (rcStrict == VINF_SUCCESS)
9274 {
9275 pCtx->eflags.u32 &= ~(X86_EFL_IF | X86_EFL_TF | X86_EFL_RF | X86_EFL_AC);
9276 pCtx->rip = IdtEntry.offSel;
9277 pCtx->cs.Sel = IdtEntry.uSel;
9278 pCtx->cs.ValidSel = IdtEntry.uSel;
9279 pCtx->cs.u64Base = IdtEntry.uSel << cbIdtEntry;
9280 if ( uIntType == VMX_ENTRY_INT_INFO_TYPE_HW_XCPT
9281 && uVector == X86_XCPT_PF)
9282 pCtx->cr2 = GCPtrFault;
9283
9284 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CS | HM_CHANGED_GUEST_CR2
9285 | HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
9286 | HM_CHANGED_GUEST_RSP);
9287
9288 /*
9289 * If we delivered a hardware exception (other than an NMI) and if there was
9290 * block-by-STI in effect, we should clear it.
9291 */
9292 if (*pfIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
9293 {
9294 Assert( uIntType != VMX_ENTRY_INT_INFO_TYPE_NMI
9295 && uIntType != VMX_ENTRY_INT_INFO_TYPE_EXT_INT);
9296 Log4Func(("Clearing inhibition due to STI\n"));
9297 *pfIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
9298 }
9299
9300 Log4(("Injected real-mode: u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x Eflags=%#x CS:EIP=%04x:%04x\n",
9301 u32IntInfo, u32ErrCode, cbInstr, pCtx->eflags.u, pCtx->cs.Sel, pCtx->eip));
9302
9303 /*
9304 * The event has been truly dispatched to the guest. Mark it as no longer pending so
9305 * we don't attempt to undo it if we are returning to ring-3 before executing guest code.
9306 */
9307 pVCpu->hm.s.Event.fPending = false;
9308
9309 /*
9310 * If we eventually support nested-guest execution without unrestricted guest execution,
9311 * we should set fInterceptEvents here.
9312 */
9313 Assert(!pVmxTransient->fIsNestedGuest);
9314
9315 /* If we're stepping and we've changed cs:rip above, bail out of the VMX R0 execution loop. */
9316 if (fStepping)
9317 rcStrict = VINF_EM_DBG_STEPPED;
9318 }
9319 AssertMsg(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
9320 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
9321 return rcStrict;
9322 }
9323 }
9324
9325 /*
9326 * Validate.
9327 */
9328 Assert(VMX_ENTRY_INT_INFO_IS_VALID(u32IntInfo)); /* Bit 31 (Valid bit) must be set by caller. */
9329 Assert(!(u32IntInfo & VMX_BF_ENTRY_INT_INFO_RSVD_12_30_MASK)); /* Bits 30:12 MBZ. */
9330
9331 /*
9332 * Inject the event into the VMCS.
9333 */
9334 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, u32IntInfo);
9335 if (VMX_ENTRY_INT_INFO_IS_ERROR_CODE_VALID(u32IntInfo))
9336 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE, u32ErrCode);
9337 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH, cbInstr);
9338 AssertRCReturn(rc, rc);
9339
9340 /*
9341 * Update guest CR2 if this is a page-fault.
9342 */
9343 if (VMX_ENTRY_INT_INFO_IS_XCPT_PF(u32IntInfo))
9344 pCtx->cr2 = GCPtrFault;
9345
9346 Log4(("Injecting u32IntInfo=%#x u32ErrCode=%#x cbInstr=%#x CR2=%#RX64\n", u32IntInfo, u32ErrCode, cbInstr, pCtx->cr2));
9347 return VINF_SUCCESS;
9348}
9349
9350
9351/**
9352 * Evaluates the event to be delivered to the guest and sets it as the pending
9353 * event.
9354 *
9355 * @returns Strict VBox status code (i.e. informational status codes too).
9356 * @param pVCpu The cross context virtual CPU structure.
9357 * @param pVmxTransient The VMX-transient structure.
9358 * @param pfIntrState Where to store the VT-x guest-interruptibility state.
9359 */
9360static VBOXSTRICTRC hmR0VmxEvaluatePendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t *pfIntrState)
9361{
9362 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9363 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9364 bool const fIsNestedGuest = pVmxTransient->fIsNestedGuest;
9365
9366 /* Get the current interruptibility-state of the guest and then figure out what can be injected. */
9367 uint32_t const fIntrState = hmR0VmxGetGuestIntrState(pVCpu, pVmxTransient);
9368 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9369 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9370 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9371
9372 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pCtx->fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9373 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9374 Assert(!fBlockSti || pCtx->eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9375 Assert(!TRPMHasTrap(pVCpu));
9376 Assert(pfIntrState);
9377
9378 *pfIntrState = fIntrState;
9379
9380 /*
9381 * Toggling of interrupt force-flags here is safe since we update TRPM on premature exits
9382 * to ring-3 before executing guest code, see hmR0VmxExitToRing3(). We must NOT restore these force-flags.
9383 */
9384 /** @todo SMI. SMIs take priority over NMIs. */
9385 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INTERRUPT_NMI)) /* NMI. NMIs take priority over regular interrupts. */
9386 {
9387 /* On some CPUs block-by-STI also blocks NMIs. See Intel spec. 26.3.1.5 "Checks On Guest Non-Register State". */
9388 if ( !pVCpu->hm.s.Event.fPending
9389 && !fBlockNmi
9390 && !fBlockSti
9391 && !fBlockMovSS)
9392 {
9393#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9394 if ( fIsNestedGuest
9395 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_NMI_EXIT))
9396 return IEMExecVmxVmexitXcptNmi(pVCpu);
9397#endif
9398 hmR0VmxSetPendingXcptNmi(pVCpu);
9399 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INTERRUPT_NMI);
9400 Log4Func(("Pending NMI\n"));
9401 }
9402 else if (!fIsNestedGuest)
9403 hmR0VmxSetNmiWindowExitVmcs(pVCpu, pVmcsInfo);
9404 }
9405 /*
9406 * Check if the guest can receive external interrupts (PIC/APIC). Once PDMGetInterrupt() returns
9407 * a valid interrupt we -must- deliver the interrupt. We can no longer re-request it from the APIC.
9408 */
9409 else if ( VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_INTERRUPT_APIC | VMCPU_FF_INTERRUPT_PIC)
9410 && !pVCpu->hm.s.fSingleInstruction)
9411 {
9412 Assert(!DBGFIsStepping(pVCpu));
9413 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
9414 AssertRCReturn(rc, rc);
9415 bool const fBlockInt = !(pCtx->eflags.u32 & X86_EFL_IF);
9416 if ( !pVCpu->hm.s.Event.fPending
9417 && !fBlockInt
9418 && !fBlockSti
9419 && !fBlockMovSS)
9420 {
9421#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9422 if ( fIsNestedGuest
9423 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT))
9424 {
9425 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, 0/* uVector */, true /* fIntPending */);
9426 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9427 return rcStrict;
9428 }
9429#endif
9430 uint8_t u8Interrupt;
9431 rc = PDMGetInterrupt(pVCpu, &u8Interrupt);
9432 if (RT_SUCCESS(rc))
9433 {
9434#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
9435 if ( fIsNestedGuest
9436 && CPUMIsGuestVmxPinCtlsSet(pVCpu, pCtx, VMX_PIN_CTLS_EXT_INT_EXIT)
9437 && CPUMIsGuestVmxExitCtlsSet(pVCpu, pCtx, VMX_EXIT_CTLS_ACK_EXT_INT))
9438 {
9439 VBOXSTRICTRC rcStrict = IEMExecVmxVmexitExtInt(pVCpu, u8Interrupt, false /* fIntPending */);
9440 if (rcStrict != VINF_VMX_INTERCEPT_NOT_ACTIVE)
9441 return rcStrict;
9442 }
9443#endif
9444 hmR0VmxSetPendingExtInt(pVCpu, u8Interrupt);
9445 Log4Func(("Pending external interrupt vector %#x\n", u8Interrupt));
9446 }
9447 else if (rc == VERR_APIC_INTR_MASKED_BY_TPR)
9448 {
9449 if ( !fIsNestedGuest
9450 && (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW))
9451 hmR0VmxApicSetTprThreshold(pVCpu, pVmcsInfo, u8Interrupt >> 4);
9452 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchTprMaskedIrq);
9453
9454 /*
9455 * If the CPU doesn't have TPR shadowing, we will always get a VM-exit on TPR changes and
9456 * APICSetTpr() will end up setting the VMCPU_FF_INTERRUPT_APIC if required, so there is no
9457 * need to re-set this force-flag here.
9458 */
9459 }
9460 else
9461 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchGuestIrq);
9462 }
9463 else if (!fIsNestedGuest)
9464 hmR0VmxSetIntWindowExitVmcs(pVCpu, pVmcsInfo);
9465 }
9466
9467 return VINF_SUCCESS;
9468}
9469
9470
9471/**
9472 * Injects any pending events into the guest if the guest is in a state to
9473 * receive them.
9474 *
9475 * @returns Strict VBox status code (i.e. informational status codes too).
9476 * @param pVCpu The cross context virtual CPU structure.
9477 * @param pVmxTransient The VMX-transient structure.
9478 * @param fIntrState The VT-x guest-interruptibility state.
9479 * @param fStepping Whether we are single-stepping the guest using the
9480 * hypervisor debugger and should return
9481 * VINF_EM_DBG_STEPPED if the event was dispatched
9482 * directly.
9483 */
9484static VBOXSTRICTRC hmR0VmxInjectPendingEvent(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t fIntrState, bool fStepping)
9485{
9486 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9487 Assert(VMMRZCallRing3IsEnabled(pVCpu));
9488
9489 bool const fBlockMovSS = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS);
9490 bool const fBlockSti = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI);
9491
9492 Assert(!fBlockSti || !(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_RFLAGS));
9493 Assert(!fBlockSti || pVCpu->cpum.GstCtx.eflags.Bits.u1IF); /* Cannot set block-by-STI when interrupts are disabled. */
9494 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI)); /* We don't support block-by-SMI yet.*/
9495 Assert(!TRPMHasTrap(pVCpu));
9496
9497 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
9498 if (pVCpu->hm.s.Event.fPending)
9499 {
9500 /*
9501 * Do -not- clear any interrupt-window exiting control here. We might have an interrupt
9502 * pending even while injecting an event and in this case, we want a VM-exit as soon as
9503 * the guest is ready for the next interrupt, see @bugref{6208#c45}.
9504 *
9505 * See Intel spec. 26.6.5 "Interrupt-Window Exiting and Virtual-Interrupt Delivery".
9506 */
9507 uint32_t const uIntType = VMX_ENTRY_INT_INFO_TYPE(pVCpu->hm.s.Event.u64IntInfo);
9508#ifdef VBOX_STRICT
9509 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9510 {
9511 bool const fBlockInt = !(pVCpu->cpum.GstCtx.eflags.u32 & X86_EFL_IF);
9512 Assert(!fBlockInt);
9513 Assert(!fBlockSti);
9514 Assert(!fBlockMovSS);
9515 }
9516 else if (uIntType == VMX_ENTRY_INT_INFO_TYPE_NMI)
9517 {
9518 bool const fBlockNmi = RT_BOOL(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI);
9519 Assert(!fBlockSti);
9520 Assert(!fBlockMovSS);
9521 Assert(!fBlockNmi);
9522 }
9523#endif
9524 Log4(("Injecting pending event vcpu[%RU32] u64IntInfo=%#RX64 Type=%#RX32\n", pVCpu->idCpu, pVCpu->hm.s.Event.u64IntInfo,
9525 uIntType));
9526
9527 /*
9528 * Inject the event and get any changes to the guest-interruptibility state.
9529 *
9530 * The guest-interruptibility state may need to be updated if we inject the event
9531 * into the guest IDT ourselves (for real-on-v86 guest injecting software interrupts).
9532 */
9533 rcStrict = hmR0VmxInjectEventVmcs(pVCpu, pVmxTransient, &pVCpu->hm.s.Event, fStepping, &fIntrState);
9534 AssertRCReturn(VBOXSTRICTRC_VAL(rcStrict), rcStrict);
9535
9536 if (uIntType == VMX_ENTRY_INT_INFO_TYPE_EXT_INT)
9537 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterrupt);
9538 else
9539 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectXcpt);
9540 }
9541
9542 /*
9543 * Update the guest-interruptibility state.
9544 *
9545 * This is required for the real-on-v86 software interrupt injection case above, as well as
9546 * updates to the guest state from ring-3 or IEM/REM.
9547 */
9548 int rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
9549 AssertRCReturn(rc, rc);
9550
9551 /*
9552 * There's no need to clear the VM-entry interruption-information field here if we're not
9553 * injecting anything. VT-x clears the valid bit on every VM-exit.
9554 *
9555 * See Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
9556 */
9557
9558 Assert(rcStrict == VINF_SUCCESS || rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping));
9559 NOREF(fBlockMovSS); NOREF(fBlockSti);
9560 return rcStrict;
9561}
9562
9563
9564/**
9565 * Enters the VT-x session.
9566 *
9567 * @returns VBox status code.
9568 * @param pVCpu The cross context virtual CPU structure.
9569 */
9570VMMR0DECL(int) VMXR0Enter(PVMCPU pVCpu)
9571{
9572 AssertPtr(pVCpu);
9573 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fSupported);
9574 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9575
9576 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9577 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9578 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9579
9580#ifdef VBOX_STRICT
9581 /* At least verify VMX is enabled, since we can't check if we're in VMX root mode without #GP'ing. */
9582 RTCCUINTREG uHostCr4 = ASMGetCR4();
9583 if (!(uHostCr4 & X86_CR4_VMXE))
9584 {
9585 LogRelFunc(("X86_CR4_VMXE bit in CR4 is not set!\n"));
9586 return VERR_VMX_X86_CR4_VMXE_CLEARED;
9587 }
9588#endif
9589
9590 /*
9591 * Load the appropriate VMCS as the current and active one.
9592 */
9593 PVMXVMCSINFO pVmcsInfo;
9594 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx);
9595 if (!fInNestedGuestMode)
9596 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfo;
9597 else
9598 pVmcsInfo = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
9599 int rc = hmR0VmxLoadVmcs(pVmcsInfo);
9600 if (RT_SUCCESS(rc))
9601 {
9602 pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs = fInNestedGuestMode;
9603 pVCpu->hm.s.fLeaveDone = false;
9604 Log4Func(("Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9605
9606 /*
9607 * Do the EMT scheduled L1D flush here if needed.
9608 */
9609 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9610 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9611 else if (pVCpu->CTX_SUFF(pVM)->hm.s.fMdsClearOnSched)
9612 hmR0MdsClear();
9613 }
9614 return rc;
9615}
9616
9617
9618/**
9619 * The thread-context callback (only on platforms which support it).
9620 *
9621 * @param enmEvent The thread-context event.
9622 * @param pVCpu The cross context virtual CPU structure.
9623 * @param fGlobalInit Whether global VT-x/AMD-V init. was used.
9624 * @thread EMT(pVCpu)
9625 */
9626VMMR0DECL(void) VMXR0ThreadCtxCallback(RTTHREADCTXEVENT enmEvent, PVMCPU pVCpu, bool fGlobalInit)
9627{
9628 AssertPtr(pVCpu);
9629 RT_NOREF1(fGlobalInit);
9630
9631 switch (enmEvent)
9632 {
9633 case RTTHREADCTXEVENT_OUT:
9634 {
9635 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9636 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9637 VMCPU_ASSERT_EMT(pVCpu);
9638
9639 /* No longjmps (logger flushes, locks) in this fragile context. */
9640 VMMRZCallRing3Disable(pVCpu);
9641 Log4Func(("Preempting: HostCpuId=%u\n", RTMpCpuId()));
9642
9643 /* Restore host-state (FPU, debug etc.) */
9644 if (!pVCpu->hm.s.fLeaveDone)
9645 {
9646 /*
9647 * Do -not- import the guest-state here as we might already be in the middle of importing
9648 * it, esp. bad if we're holding the PGM lock, see comment in hmR0VmxImportGuestState().
9649 */
9650 hmR0VmxLeave(pVCpu, false /* fImportState */);
9651 pVCpu->hm.s.fLeaveDone = true;
9652 }
9653
9654 /* Leave HM context, takes care of local init (term). */
9655 int rc = HMR0LeaveCpu(pVCpu);
9656 AssertRC(rc);
9657
9658 /* Restore longjmp state. */
9659 VMMRZCallRing3Enable(pVCpu);
9660 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatSwitchPreempt);
9661 break;
9662 }
9663
9664 case RTTHREADCTXEVENT_IN:
9665 {
9666 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9667 Assert(VMMR0ThreadCtxHookIsEnabled(pVCpu));
9668 VMCPU_ASSERT_EMT(pVCpu);
9669
9670 /* No longjmps here, as we don't want to trigger preemption (& its hook) while resuming. */
9671 VMMRZCallRing3Disable(pVCpu);
9672 Log4Func(("Resumed: HostCpuId=%u\n", RTMpCpuId()));
9673
9674 /* Initialize the bare minimum state required for HM. This takes care of
9675 initializing VT-x if necessary (onlined CPUs, local init etc.) */
9676 int rc = hmR0EnterCpu(pVCpu);
9677 AssertRC(rc);
9678 Assert( (pVCpu->hm.s.fCtxChanged & (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9679 == (HM_CHANGED_HOST_CONTEXT | HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE));
9680
9681 /* Load the active VMCS as the current one. */
9682 PVMXVMCSINFO pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
9683 rc = hmR0VmxLoadVmcs(pVmcsInfo);
9684 AssertRC(rc);
9685 Log4Func(("Resumed: Loaded Vmcs. HostCpuId=%u\n", RTMpCpuId()));
9686 pVCpu->hm.s.fLeaveDone = false;
9687
9688 /* Do the EMT scheduled L1D flush if needed. */
9689 if (pVCpu->CTX_SUFF(pVM)->hm.s.fL1dFlushOnSched)
9690 ASMWrMsr(MSR_IA32_FLUSH_CMD, MSR_IA32_FLUSH_CMD_F_L1D);
9691
9692 /* Restore longjmp state. */
9693 VMMRZCallRing3Enable(pVCpu);
9694 break;
9695 }
9696
9697 default:
9698 break;
9699 }
9700}
9701
9702
9703/**
9704 * Exports the host state into the VMCS host-state area.
9705 * Sets up the VM-exit MSR-load area.
9706 *
9707 * The CPU state will be loaded from these fields on every successful VM-exit.
9708 *
9709 * @returns VBox status code.
9710 * @param pVCpu The cross context virtual CPU structure.
9711 *
9712 * @remarks No-long-jump zone!!!
9713 */
9714static int hmR0VmxExportHostState(PVMCPU pVCpu)
9715{
9716 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9717
9718 int rc = VINF_SUCCESS;
9719 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
9720 {
9721 rc = hmR0VmxExportHostControlRegs();
9722 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9723
9724 rc = hmR0VmxExportHostSegmentRegs(pVCpu);
9725 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9726
9727 rc = hmR0VmxExportHostMsrs(pVCpu);
9728 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9729
9730 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_HOST_CONTEXT;
9731 }
9732 return rc;
9733}
9734
9735
9736/**
9737 * Saves the host state in the VMCS host-state.
9738 *
9739 * @returns VBox status code.
9740 * @param pVCpu The cross context virtual CPU structure.
9741 *
9742 * @remarks No-long-jump zone!!!
9743 */
9744VMMR0DECL(int) VMXR0ExportHostState(PVMCPU pVCpu)
9745{
9746 AssertPtr(pVCpu);
9747 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9748
9749 /*
9750 * Export the host state here while entering HM context.
9751 * When thread-context hooks are used, we might get preempted and have to re-save the host
9752 * state but most of the time we won't be, so do it here before we disable interrupts.
9753 */
9754 return hmR0VmxExportHostState(pVCpu);
9755}
9756
9757
9758/**
9759 * Exports the guest state into the VMCS guest-state area.
9760 *
9761 * The will typically be done before VM-entry when the guest-CPU state and the
9762 * VMCS state may potentially be out of sync.
9763 *
9764 * Sets up the VM-entry MSR-load and VM-exit MSR-store areas. Sets up the
9765 * VM-entry controls.
9766 * Sets up the appropriate VMX non-root function to execute guest code based on
9767 * the guest CPU mode.
9768 *
9769 * @returns VBox strict status code.
9770 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9771 * without unrestricted guest execution and the VMMDev is not presently
9772 * mapped (e.g. EFI32).
9773 *
9774 * @param pVCpu The cross context virtual CPU structure.
9775 * @param pVmxTransient The VMX-transient structure.
9776 *
9777 * @remarks No-long-jump zone!!!
9778 */
9779static VBOXSTRICTRC hmR0VmxExportGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9780{
9781 AssertPtr(pVCpu);
9782 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9783 LogFlowFunc(("pVCpu=%p\n", pVCpu));
9784
9785 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExportGuestState, x);
9786
9787 /*
9788 * Determine real-on-v86 mode.
9789 * Used when the guest is in real-mode and unrestricted guest execution is not used.
9790 */
9791 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
9792 if ( pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
9793 || !CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx))
9794 pVmcsInfo->RealMode. fRealOnV86Active = false;
9795 else
9796 {
9797 Assert(!pVmxTransient->fIsNestedGuest);
9798 pVmcsInfo->RealMode.fRealOnV86Active = true;
9799 }
9800
9801 /*
9802 * Any ordering dependency among the sub-functions below must be explicitly stated using comments.
9803 * Ideally, assert that the cross-dependent bits are up-to-date at the point of using it.
9804 */
9805 /** @todo r=ramshankar: Move hmR0VmxSelectVMRunHandler inside
9806 * hmR0VmxExportGuestEntryExitCtls and do it conditionally. There shouldn't
9807 * be a need to evaluate this everytime since I'm pretty sure we intercept
9808 * all guest paging mode changes. */
9809 int rc = hmR0VmxSelectVMRunHandler(pVCpu, pVmxTransient);
9810 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9811
9812 rc = hmR0VmxExportGuestEntryExitCtls(pVCpu, pVmxTransient);
9813 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9814
9815 rc = hmR0VmxExportGuestCR0(pVCpu, pVmxTransient);
9816 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9817
9818 VBOXSTRICTRC rcStrict = hmR0VmxExportGuestCR3AndCR4(pVCpu, pVmxTransient);
9819 if (rcStrict == VINF_SUCCESS)
9820 { /* likely */ }
9821 else
9822 {
9823 Assert(rcStrict == VINF_EM_RESCHEDULE_REM || RT_FAILURE_NP(rcStrict));
9824 return rcStrict;
9825 }
9826
9827 rc = hmR0VmxExportGuestSegRegsXdtr(pVCpu, pVmxTransient);
9828 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9829
9830 rc = hmR0VmxExportGuestMsrs(pVCpu, pVmxTransient);
9831 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9832
9833 rc = hmR0VmxExportGuestApicTpr(pVCpu, pVmxTransient);
9834 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9835
9836 rc = hmR0VmxExportGuestXcptIntercepts(pVCpu, pVmxTransient);
9837 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9838
9839 rc = hmR0VmxExportGuestRip(pVCpu);
9840 rc |= hmR0VmxExportGuestRsp(pVCpu);
9841 rc |= hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9842 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9843
9844 rc = hmR0VmxExportGuestHwvirtState(pVCpu, pVmxTransient);
9845 AssertLogRelMsgRCReturn(rc, ("rc=%Rrc\n", rc), rc);
9846
9847 /* Clear any bits that may be set but exported unconditionally or unused/reserved bits. */
9848 ASMAtomicUoAndU64(&pVCpu->hm.s.fCtxChanged, ~( (HM_CHANGED_GUEST_GPRS_MASK & ~HM_CHANGED_GUEST_RSP)
9849 | HM_CHANGED_GUEST_CR2
9850 | (HM_CHANGED_GUEST_DR_MASK & ~HM_CHANGED_GUEST_DR7)
9851 | HM_CHANGED_GUEST_X87
9852 | HM_CHANGED_GUEST_SSE_AVX
9853 | HM_CHANGED_GUEST_OTHER_XSAVE
9854 | HM_CHANGED_GUEST_XCRx
9855 | HM_CHANGED_GUEST_KERNEL_GS_BASE /* Part of lazy or auto load-store MSRs. */
9856 | HM_CHANGED_GUEST_SYSCALL_MSRS /* Part of lazy or auto load-store MSRs. */
9857 | HM_CHANGED_GUEST_TSC_AUX
9858 | HM_CHANGED_GUEST_OTHER_MSRS
9859 | (HM_CHANGED_KEEPER_STATE_MASK & ~HM_CHANGED_VMX_MASK)));
9860
9861 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExportGuestState, x);
9862 return rc;
9863}
9864
9865
9866/**
9867 * Exports the state shared between the host and guest into the VMCS.
9868 *
9869 * @param pVCpu The cross context virtual CPU structure.
9870 * @param pVmxTransient The VMX-transient structure.
9871 *
9872 * @remarks No-long-jump zone!!!
9873 */
9874static void hmR0VmxExportSharedState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9875{
9876 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
9877 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9878
9879 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_DR_MASK)
9880 {
9881 int rc = hmR0VmxExportSharedDebugState(pVCpu, pVmxTransient);
9882 AssertRC(rc);
9883 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_GUEST_DR_MASK;
9884
9885 /* Loading shared debug bits might have changed eflags.TF bit for debugging purposes. */
9886 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_GUEST_RFLAGS)
9887 {
9888 rc = hmR0VmxExportGuestRflags(pVCpu, pVmxTransient);
9889 AssertRC(rc);
9890 }
9891 }
9892
9893 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_GUEST_LAZY_MSRS)
9894 {
9895 hmR0VmxLazyLoadGuestMsrs(pVCpu);
9896 pVCpu->hm.s.fCtxChanged &= ~HM_CHANGED_VMX_GUEST_LAZY_MSRS;
9897 }
9898
9899 AssertMsg(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE),
9900 ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
9901}
9902
9903
9904/**
9905 * Worker for loading the guest-state bits in the inner VT-x execution loop.
9906 *
9907 * @returns Strict VBox status code (i.e. informational status codes too).
9908 * @retval VINF_EM_RESCHEDULE_REM if we try to emulate non-paged guest code
9909 * without unrestricted guest execution and the VMMDev is not presently
9910 * mapped (e.g. EFI32).
9911 *
9912 * @param pVCpu The cross context virtual CPU structure.
9913 * @param pVmxTransient The VMX-transient structure.
9914 *
9915 * @remarks No-long-jump zone!!!
9916 */
9917static VBOXSTRICTRC hmR0VmxExportGuestStateOptimal(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
9918{
9919 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
9920 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9921 Assert(VMMR0IsLogFlushDisabled(pVCpu));
9922
9923#ifdef HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE
9924 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
9925#endif
9926
9927 /*
9928 * For many exits it's only RIP that changes and hence try to export it first
9929 * without going through a lot of change flag checks.
9930 */
9931 VBOXSTRICTRC rcStrict;
9932 uint64_t fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9933 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9934 if ((fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)) == HM_CHANGED_GUEST_RIP)
9935 {
9936 rcStrict = hmR0VmxExportGuestRip(pVCpu);
9937 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9938 { /* likely */}
9939 else
9940 AssertMsgFailedReturn(("Failed to export guest RIP! rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)), rcStrict);
9941 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportMinimal);
9942 }
9943 else if (fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE))
9944 {
9945 rcStrict = hmR0VmxExportGuestState(pVCpu, pVmxTransient);
9946 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
9947 { /* likely */}
9948 else
9949 {
9950 AssertMsg(rcStrict == VINF_EM_RESCHEDULE_REM, ("Failed to export guest state! rc=%Rrc\n",
9951 VBOXSTRICTRC_VAL(rcStrict)));
9952 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
9953 return rcStrict;
9954 }
9955 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportFull);
9956 }
9957 else
9958 rcStrict = VINF_SUCCESS;
9959
9960#ifdef VBOX_STRICT
9961 /* All the guest state bits should be loaded except maybe the host context and/or the shared host/guest bits. */
9962 fCtxChanged = ASMAtomicUoReadU64(&pVCpu->hm.s.fCtxChanged);
9963 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
9964 AssertMsg(!(fCtxChanged & (HM_CHANGED_ALL_GUEST & ~HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)),
9965 ("fCtxChanged=%#RX64\n", fCtxChanged));
9966#endif
9967 return rcStrict;
9968}
9969
9970
9971/**
9972 * Tries to determine what part of the guest-state VT-x has deemed as invalid
9973 * and update error record fields accordingly.
9974 *
9975 * @returns VMX_IGS_* error codes.
9976 * @retval VMX_IGS_REASON_NOT_FOUND if this function could not find anything
9977 * wrong with the guest state.
9978 *
9979 * @param pVCpu The cross context virtual CPU structure.
9980 * @param pVmcsInfo The VMCS info. object.
9981 *
9982 * @remarks This function assumes our cache of the VMCS controls
9983 * are valid, i.e. hmR0VmxCheckVmcsCtls() succeeded.
9984 */
9985static uint32_t hmR0VmxCheckGuestState(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
9986{
9987#define HMVMX_ERROR_BREAK(err) { uError = (err); break; }
9988#define HMVMX_CHECK_BREAK(expr, err) do { \
9989 if (!(expr)) { uError = (err); break; } \
9990 } while (0)
9991
9992 int rc;
9993 PVM pVM = pVCpu->CTX_SUFF(pVM);
9994 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
9995 uint32_t uError = VMX_IGS_ERROR;
9996 uint32_t u32Val;
9997 bool const fUnrestrictedGuest = pVM->hm.s.vmx.fUnrestrictedGuest;
9998
9999 do
10000 {
10001 /*
10002 * CR0.
10003 */
10004 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10005 uint32_t fSetCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10006 uint32_t const fZapCr0 = (uint32_t)(pVM->hm.s.vmx.Msrs.u64Cr0Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr0Fixed1);
10007 /* Exceptions for unrestricted guest execution for fixed CR0 bits (PE, PG).
10008 See Intel spec. 26.3.1 "Checks on Guest Control Registers, Debug Registers and MSRs." */
10009 if (fUnrestrictedGuest)
10010 fSetCr0 &= ~(X86_CR0_PE | X86_CR0_PG);
10011
10012 uint32_t u32GuestCr0;
10013 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32GuestCr0);
10014 AssertRCBreak(rc);
10015 HMVMX_CHECK_BREAK((u32GuestCr0 & fSetCr0) == fSetCr0, VMX_IGS_CR0_FIXED1);
10016 HMVMX_CHECK_BREAK(!(u32GuestCr0 & ~fZapCr0), VMX_IGS_CR0_FIXED0);
10017 if ( !fUnrestrictedGuest
10018 && (u32GuestCr0 & X86_CR0_PG)
10019 && !(u32GuestCr0 & X86_CR0_PE))
10020 {
10021 HMVMX_ERROR_BREAK(VMX_IGS_CR0_PG_PE_COMBO);
10022 }
10023
10024 /*
10025 * CR4.
10026 */
10027 /** @todo Why do we need to OR and AND the fixed-0 and fixed-1 bits below? */
10028 uint64_t const fSetCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 & pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10029 uint64_t const fZapCr4 = (pVM->hm.s.vmx.Msrs.u64Cr4Fixed0 | pVM->hm.s.vmx.Msrs.u64Cr4Fixed1);
10030
10031 uint32_t u32GuestCr4;
10032 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR4, &u32GuestCr4);
10033 AssertRCBreak(rc);
10034 HMVMX_CHECK_BREAK((u32GuestCr4 & fSetCr4) == fSetCr4, VMX_IGS_CR4_FIXED1);
10035 HMVMX_CHECK_BREAK(!(u32GuestCr4 & ~fZapCr4), VMX_IGS_CR4_FIXED0);
10036
10037 /*
10038 * IA32_DEBUGCTL MSR.
10039 */
10040 uint64_t u64Val;
10041 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_DEBUGCTL_FULL, &u64Val);
10042 AssertRCBreak(rc);
10043 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10044 && (u64Val & 0xfffffe3c)) /* Bits 31:9, bits 5:2 MBZ. */
10045 {
10046 HMVMX_ERROR_BREAK(VMX_IGS_DEBUGCTL_MSR_RESERVED);
10047 }
10048 uint64_t u64DebugCtlMsr = u64Val;
10049
10050#ifdef VBOX_STRICT
10051 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY, &u32Val);
10052 AssertRCBreak(rc);
10053 Assert(u32Val == pVmcsInfo->u32EntryCtls);
10054#endif
10055 bool const fLongModeGuest = RT_BOOL(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_IA32E_MODE_GUEST);
10056
10057 /*
10058 * RIP and RFLAGS.
10059 */
10060 uint32_t u32Eflags;
10061#if HC_ARCH_BITS == 64
10062 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RIP, &u64Val);
10063 AssertRCBreak(rc);
10064 /* pCtx->rip can be different than the one in the VMCS (e.g. run guest code and VM-exits that don't update it). */
10065 if ( !fLongModeGuest
10066 || !pCtx->cs.Attr.n.u1Long)
10067 {
10068 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffff00000000)), VMX_IGS_LONGMODE_RIP_INVALID);
10069 }
10070 /** @todo If the processor supports N < 64 linear-address bits, bits 63:N
10071 * must be identical if the "IA-32e mode guest" VM-entry
10072 * control is 1 and CS.L is 1. No check applies if the
10073 * CPU supports 64 linear-address bits. */
10074
10075 /* Flags in pCtx can be different (real-on-v86 for instance). We are only concerned about the VMCS contents here. */
10076 rc = VMXReadVmcs64(VMX_VMCS_GUEST_RFLAGS, &u64Val);
10077 AssertRCBreak(rc);
10078 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffc08028)), /* Bit 63:22, Bit 15, 5, 3 MBZ. */
10079 VMX_IGS_RFLAGS_RESERVED);
10080 HMVMX_CHECK_BREAK((u64Val & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10081 u32Eflags = u64Val;
10082#else
10083 rc = VMXReadVmcs32(VMX_VMCS_GUEST_RFLAGS, &u32Eflags);
10084 AssertRCBreak(rc);
10085 HMVMX_CHECK_BREAK(!(u32Eflags & 0xffc08028), VMX_IGS_RFLAGS_RESERVED); /* Bit 31:22, Bit 15, 5, 3 MBZ. */
10086 HMVMX_CHECK_BREAK((u32Eflags & X86_EFL_RA1_MASK), VMX_IGS_RFLAGS_RESERVED1); /* Bit 1 MB1. */
10087#endif
10088
10089 if ( fLongModeGuest
10090 || ( fUnrestrictedGuest
10091 && !(u32GuestCr0 & X86_CR0_PE)))
10092 {
10093 HMVMX_CHECK_BREAK(!(u32Eflags & X86_EFL_VM), VMX_IGS_RFLAGS_VM_INVALID);
10094 }
10095
10096 uint32_t u32EntryInfo;
10097 rc = VMXReadVmcs32(VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO, &u32EntryInfo);
10098 AssertRCBreak(rc);
10099 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10100 HMVMX_CHECK_BREAK(u32Eflags & X86_EFL_IF, VMX_IGS_RFLAGS_IF_INVALID);
10101
10102 /*
10103 * 64-bit checks.
10104 */
10105#if HC_ARCH_BITS == 64
10106 if (fLongModeGuest)
10107 {
10108 HMVMX_CHECK_BREAK(u32GuestCr0 & X86_CR0_PG, VMX_IGS_CR0_PG_LONGMODE);
10109 HMVMX_CHECK_BREAK(u32GuestCr4 & X86_CR4_PAE, VMX_IGS_CR4_PAE_LONGMODE);
10110 }
10111
10112 if ( !fLongModeGuest
10113 && (u32GuestCr4 & X86_CR4_PCIDE))
10114 {
10115 HMVMX_ERROR_BREAK(VMX_IGS_CR4_PCIDE);
10116 }
10117
10118 /** @todo CR3 field must be such that bits 63:52 and bits in the range
10119 * 51:32 beyond the processor's physical-address width are 0. */
10120
10121 if ( (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_DEBUG)
10122 && (pCtx->dr[7] & X86_DR7_MBZ_MASK))
10123 {
10124 HMVMX_ERROR_BREAK(VMX_IGS_DR7_RESERVED);
10125 }
10126
10127 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_ESP, &u64Val);
10128 AssertRCBreak(rc);
10129 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_ESP_NOT_CANONICAL);
10130
10131 rc = VMXReadVmcs64(VMX_VMCS_HOST_SYSENTER_EIP, &u64Val);
10132 AssertRCBreak(rc);
10133 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_SYSENTER_EIP_NOT_CANONICAL);
10134#endif
10135
10136 /*
10137 * PERF_GLOBAL MSR.
10138 */
10139 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PERF_MSR)
10140 {
10141 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PERF_GLOBAL_CTRL_FULL, &u64Val);
10142 AssertRCBreak(rc);
10143 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffff8fffffffc)),
10144 VMX_IGS_PERF_GLOBAL_MSR_RESERVED); /* Bits 63:35, bits 31:2 MBZ. */
10145 }
10146
10147 /*
10148 * PAT MSR.
10149 */
10150 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_PAT_MSR)
10151 {
10152 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PAT_FULL, &u64Val);
10153 AssertRCBreak(rc);
10154 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0x707070707070707)), VMX_IGS_PAT_MSR_RESERVED);
10155 for (unsigned i = 0; i < 8; i++)
10156 {
10157 uint8_t u8Val = (u64Val & 0xff);
10158 if ( u8Val != 0 /* UC */
10159 && u8Val != 1 /* WC */
10160 && u8Val != 4 /* WT */
10161 && u8Val != 5 /* WP */
10162 && u8Val != 6 /* WB */
10163 && u8Val != 7 /* UC- */)
10164 {
10165 HMVMX_ERROR_BREAK(VMX_IGS_PAT_MSR_INVALID);
10166 }
10167 u64Val >>= 8;
10168 }
10169 }
10170
10171 /*
10172 * EFER MSR.
10173 */
10174 if (pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_LOAD_EFER_MSR)
10175 {
10176 Assert(pVM->hm.s.vmx.fSupportsVmcsEfer);
10177 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_EFER_FULL, &u64Val);
10178 AssertRCBreak(rc);
10179 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xfffffffffffff2fe)),
10180 VMX_IGS_EFER_MSR_RESERVED); /* Bits 63:12, bit 9, bits 7:1 MBZ. */
10181 HMVMX_CHECK_BREAK(RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL( pVmcsInfo->u32EntryCtls
10182 & VMX_ENTRY_CTLS_IA32E_MODE_GUEST),
10183 VMX_IGS_EFER_LMA_GUEST_MODE_MISMATCH);
10184 /** @todo r=ramshankar: Unrestricted check here is probably wrong, see
10185 * iemVmxVmentryCheckGuestState(). */
10186 HMVMX_CHECK_BREAK( fUnrestrictedGuest
10187 || !(u32GuestCr0 & X86_CR0_PG)
10188 || RT_BOOL(u64Val & MSR_K6_EFER_LMA) == RT_BOOL(u64Val & MSR_K6_EFER_LME),
10189 VMX_IGS_EFER_LMA_LME_MISMATCH);
10190 }
10191
10192 /*
10193 * Segment registers.
10194 */
10195 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10196 || !(pCtx->ldtr.Sel & X86_SEL_LDT), VMX_IGS_LDTR_TI_INVALID);
10197 if (!(u32Eflags & X86_EFL_VM))
10198 {
10199 /* CS */
10200 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1Present, VMX_IGS_CS_ATTR_P_INVALID);
10201 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xf00), VMX_IGS_CS_ATTR_RESERVED);
10202 HMVMX_CHECK_BREAK(!(pCtx->cs.Attr.u & 0xfffe0000), VMX_IGS_CS_ATTR_RESERVED);
10203 HMVMX_CHECK_BREAK( (pCtx->cs.u32Limit & 0xfff) == 0xfff
10204 || !(pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10205 HMVMX_CHECK_BREAK( !(pCtx->cs.u32Limit & 0xfff00000)
10206 || (pCtx->cs.Attr.n.u1Granularity), VMX_IGS_CS_ATTR_G_INVALID);
10207 /* CS cannot be loaded with NULL in protected mode. */
10208 HMVMX_CHECK_BREAK(pCtx->cs.Attr.u && !(pCtx->cs.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_CS_ATTR_UNUSABLE);
10209 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u1DescType, VMX_IGS_CS_ATTR_S_INVALID);
10210 if (pCtx->cs.Attr.n.u4Type == 9 || pCtx->cs.Attr.n.u4Type == 11)
10211 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_UNEQUAL);
10212 else if (pCtx->cs.Attr.n.u4Type == 13 || pCtx->cs.Attr.n.u4Type == 15)
10213 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl <= pCtx->ss.Attr.n.u2Dpl, VMX_IGS_CS_SS_ATTR_DPL_MISMATCH);
10214 else if (pVM->hm.s.vmx.fUnrestrictedGuest && pCtx->cs.Attr.n.u4Type == 3)
10215 HMVMX_CHECK_BREAK(pCtx->cs.Attr.n.u2Dpl == 0, VMX_IGS_CS_ATTR_DPL_INVALID);
10216 else
10217 HMVMX_ERROR_BREAK(VMX_IGS_CS_ATTR_TYPE_INVALID);
10218
10219 /* SS */
10220 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10221 || (pCtx->ss.Sel & X86_SEL_RPL) == (pCtx->cs.Sel & X86_SEL_RPL), VMX_IGS_SS_CS_RPL_UNEQUAL);
10222 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u2Dpl == (pCtx->ss.Sel & X86_SEL_RPL), VMX_IGS_SS_ATTR_DPL_RPL_UNEQUAL);
10223 if ( !(pCtx->cr0 & X86_CR0_PE)
10224 || pCtx->cs.Attr.n.u4Type == 3)
10225 {
10226 HMVMX_CHECK_BREAK(!pCtx->ss.Attr.n.u2Dpl, VMX_IGS_SS_ATTR_DPL_INVALID);
10227 }
10228 if (!(pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE))
10229 {
10230 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u4Type == 3 || pCtx->ss.Attr.n.u4Type == 7, VMX_IGS_SS_ATTR_TYPE_INVALID);
10231 HMVMX_CHECK_BREAK(pCtx->ss.Attr.n.u1Present, VMX_IGS_SS_ATTR_P_INVALID);
10232 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xf00), VMX_IGS_SS_ATTR_RESERVED);
10233 HMVMX_CHECK_BREAK(!(pCtx->ss.Attr.u & 0xfffe0000), VMX_IGS_SS_ATTR_RESERVED);
10234 HMVMX_CHECK_BREAK( (pCtx->ss.u32Limit & 0xfff) == 0xfff
10235 || !(pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10236 HMVMX_CHECK_BREAK( !(pCtx->ss.u32Limit & 0xfff00000)
10237 || (pCtx->ss.Attr.n.u1Granularity), VMX_IGS_SS_ATTR_G_INVALID);
10238 }
10239
10240 /* DS, ES, FS, GS - only check for usable selectors, see hmR0VmxExportGuestSReg(). */
10241 if (!(pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE))
10242 {
10243 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_DS_ATTR_A_INVALID);
10244 HMVMX_CHECK_BREAK(pCtx->ds.Attr.n.u1Present, VMX_IGS_DS_ATTR_P_INVALID);
10245 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10246 || pCtx->ds.Attr.n.u4Type > 11
10247 || pCtx->ds.Attr.n.u2Dpl >= (pCtx->ds.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10248 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xf00), VMX_IGS_DS_ATTR_RESERVED);
10249 HMVMX_CHECK_BREAK(!(pCtx->ds.Attr.u & 0xfffe0000), VMX_IGS_DS_ATTR_RESERVED);
10250 HMVMX_CHECK_BREAK( (pCtx->ds.u32Limit & 0xfff) == 0xfff
10251 || !(pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10252 HMVMX_CHECK_BREAK( !(pCtx->ds.u32Limit & 0xfff00000)
10253 || (pCtx->ds.Attr.n.u1Granularity), VMX_IGS_DS_ATTR_G_INVALID);
10254 HMVMX_CHECK_BREAK( !(pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10255 || (pCtx->ds.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_DS_ATTR_TYPE_INVALID);
10256 }
10257 if (!(pCtx->es.Attr.u & X86DESCATTR_UNUSABLE))
10258 {
10259 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_ES_ATTR_A_INVALID);
10260 HMVMX_CHECK_BREAK(pCtx->es.Attr.n.u1Present, VMX_IGS_ES_ATTR_P_INVALID);
10261 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10262 || pCtx->es.Attr.n.u4Type > 11
10263 || pCtx->es.Attr.n.u2Dpl >= (pCtx->es.Sel & X86_SEL_RPL), VMX_IGS_DS_ATTR_DPL_RPL_UNEQUAL);
10264 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xf00), VMX_IGS_ES_ATTR_RESERVED);
10265 HMVMX_CHECK_BREAK(!(pCtx->es.Attr.u & 0xfffe0000), VMX_IGS_ES_ATTR_RESERVED);
10266 HMVMX_CHECK_BREAK( (pCtx->es.u32Limit & 0xfff) == 0xfff
10267 || !(pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10268 HMVMX_CHECK_BREAK( !(pCtx->es.u32Limit & 0xfff00000)
10269 || (pCtx->es.Attr.n.u1Granularity), VMX_IGS_ES_ATTR_G_INVALID);
10270 HMVMX_CHECK_BREAK( !(pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10271 || (pCtx->es.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_ES_ATTR_TYPE_INVALID);
10272 }
10273 if (!(pCtx->fs.Attr.u & X86DESCATTR_UNUSABLE))
10274 {
10275 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_FS_ATTR_A_INVALID);
10276 HMVMX_CHECK_BREAK(pCtx->fs.Attr.n.u1Present, VMX_IGS_FS_ATTR_P_INVALID);
10277 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10278 || pCtx->fs.Attr.n.u4Type > 11
10279 || pCtx->fs.Attr.n.u2Dpl >= (pCtx->fs.Sel & X86_SEL_RPL), VMX_IGS_FS_ATTR_DPL_RPL_UNEQUAL);
10280 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xf00), VMX_IGS_FS_ATTR_RESERVED);
10281 HMVMX_CHECK_BREAK(!(pCtx->fs.Attr.u & 0xfffe0000), VMX_IGS_FS_ATTR_RESERVED);
10282 HMVMX_CHECK_BREAK( (pCtx->fs.u32Limit & 0xfff) == 0xfff
10283 || !(pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10284 HMVMX_CHECK_BREAK( !(pCtx->fs.u32Limit & 0xfff00000)
10285 || (pCtx->fs.Attr.n.u1Granularity), VMX_IGS_FS_ATTR_G_INVALID);
10286 HMVMX_CHECK_BREAK( !(pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10287 || (pCtx->fs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_FS_ATTR_TYPE_INVALID);
10288 }
10289 if (!(pCtx->gs.Attr.u & X86DESCATTR_UNUSABLE))
10290 {
10291 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_ACCESSED, VMX_IGS_GS_ATTR_A_INVALID);
10292 HMVMX_CHECK_BREAK(pCtx->gs.Attr.n.u1Present, VMX_IGS_GS_ATTR_P_INVALID);
10293 HMVMX_CHECK_BREAK( pVM->hm.s.vmx.fUnrestrictedGuest
10294 || pCtx->gs.Attr.n.u4Type > 11
10295 || pCtx->gs.Attr.n.u2Dpl >= (pCtx->gs.Sel & X86_SEL_RPL), VMX_IGS_GS_ATTR_DPL_RPL_UNEQUAL);
10296 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xf00), VMX_IGS_GS_ATTR_RESERVED);
10297 HMVMX_CHECK_BREAK(!(pCtx->gs.Attr.u & 0xfffe0000), VMX_IGS_GS_ATTR_RESERVED);
10298 HMVMX_CHECK_BREAK( (pCtx->gs.u32Limit & 0xfff) == 0xfff
10299 || !(pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10300 HMVMX_CHECK_BREAK( !(pCtx->gs.u32Limit & 0xfff00000)
10301 || (pCtx->gs.Attr.n.u1Granularity), VMX_IGS_GS_ATTR_G_INVALID);
10302 HMVMX_CHECK_BREAK( !(pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_CODE)
10303 || (pCtx->gs.Attr.n.u4Type & X86_SEL_TYPE_READ), VMX_IGS_GS_ATTR_TYPE_INVALID);
10304 }
10305 /* 64-bit capable CPUs. */
10306#if HC_ARCH_BITS == 64
10307 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10308 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10309 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10310 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10311 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10312 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10313 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10314 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10315 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10316 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10317 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10318#endif
10319 }
10320 else
10321 {
10322 /* V86 mode checks. */
10323 uint32_t u32CSAttr, u32SSAttr, u32DSAttr, u32ESAttr, u32FSAttr, u32GSAttr;
10324 if (pVmcsInfo->RealMode.fRealOnV86Active)
10325 {
10326 u32CSAttr = 0xf3; u32SSAttr = 0xf3;
10327 u32DSAttr = 0xf3; u32ESAttr = 0xf3;
10328 u32FSAttr = 0xf3; u32GSAttr = 0xf3;
10329 }
10330 else
10331 {
10332 u32CSAttr = pCtx->cs.Attr.u; u32SSAttr = pCtx->ss.Attr.u;
10333 u32DSAttr = pCtx->ds.Attr.u; u32ESAttr = pCtx->es.Attr.u;
10334 u32FSAttr = pCtx->fs.Attr.u; u32GSAttr = pCtx->gs.Attr.u;
10335 }
10336
10337 /* CS */
10338 HMVMX_CHECK_BREAK((pCtx->cs.u64Base == (uint64_t)pCtx->cs.Sel << 4), VMX_IGS_V86_CS_BASE_INVALID);
10339 HMVMX_CHECK_BREAK(pCtx->cs.u32Limit == 0xffff, VMX_IGS_V86_CS_LIMIT_INVALID);
10340 HMVMX_CHECK_BREAK(u32CSAttr == 0xf3, VMX_IGS_V86_CS_ATTR_INVALID);
10341 /* SS */
10342 HMVMX_CHECK_BREAK((pCtx->ss.u64Base == (uint64_t)pCtx->ss.Sel << 4), VMX_IGS_V86_SS_BASE_INVALID);
10343 HMVMX_CHECK_BREAK(pCtx->ss.u32Limit == 0xffff, VMX_IGS_V86_SS_LIMIT_INVALID);
10344 HMVMX_CHECK_BREAK(u32SSAttr == 0xf3, VMX_IGS_V86_SS_ATTR_INVALID);
10345 /* DS */
10346 HMVMX_CHECK_BREAK((pCtx->ds.u64Base == (uint64_t)pCtx->ds.Sel << 4), VMX_IGS_V86_DS_BASE_INVALID);
10347 HMVMX_CHECK_BREAK(pCtx->ds.u32Limit == 0xffff, VMX_IGS_V86_DS_LIMIT_INVALID);
10348 HMVMX_CHECK_BREAK(u32DSAttr == 0xf3, VMX_IGS_V86_DS_ATTR_INVALID);
10349 /* ES */
10350 HMVMX_CHECK_BREAK((pCtx->es.u64Base == (uint64_t)pCtx->es.Sel << 4), VMX_IGS_V86_ES_BASE_INVALID);
10351 HMVMX_CHECK_BREAK(pCtx->es.u32Limit == 0xffff, VMX_IGS_V86_ES_LIMIT_INVALID);
10352 HMVMX_CHECK_BREAK(u32ESAttr == 0xf3, VMX_IGS_V86_ES_ATTR_INVALID);
10353 /* FS */
10354 HMVMX_CHECK_BREAK((pCtx->fs.u64Base == (uint64_t)pCtx->fs.Sel << 4), VMX_IGS_V86_FS_BASE_INVALID);
10355 HMVMX_CHECK_BREAK(pCtx->fs.u32Limit == 0xffff, VMX_IGS_V86_FS_LIMIT_INVALID);
10356 HMVMX_CHECK_BREAK(u32FSAttr == 0xf3, VMX_IGS_V86_FS_ATTR_INVALID);
10357 /* GS */
10358 HMVMX_CHECK_BREAK((pCtx->gs.u64Base == (uint64_t)pCtx->gs.Sel << 4), VMX_IGS_V86_GS_BASE_INVALID);
10359 HMVMX_CHECK_BREAK(pCtx->gs.u32Limit == 0xffff, VMX_IGS_V86_GS_LIMIT_INVALID);
10360 HMVMX_CHECK_BREAK(u32GSAttr == 0xf3, VMX_IGS_V86_GS_ATTR_INVALID);
10361 /* 64-bit capable CPUs. */
10362#if HC_ARCH_BITS == 64
10363 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->fs.u64Base), VMX_IGS_FS_BASE_NOT_CANONICAL);
10364 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->gs.u64Base), VMX_IGS_GS_BASE_NOT_CANONICAL);
10365 HMVMX_CHECK_BREAK( (pCtx->ldtr.Attr.u & X86DESCATTR_UNUSABLE)
10366 || X86_IS_CANONICAL(pCtx->ldtr.u64Base), VMX_IGS_LDTR_BASE_NOT_CANONICAL);
10367 HMVMX_CHECK_BREAK(!RT_HI_U32(pCtx->cs.u64Base), VMX_IGS_LONGMODE_CS_BASE_INVALID);
10368 HMVMX_CHECK_BREAK((pCtx->ss.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ss.u64Base),
10369 VMX_IGS_LONGMODE_SS_BASE_INVALID);
10370 HMVMX_CHECK_BREAK((pCtx->ds.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->ds.u64Base),
10371 VMX_IGS_LONGMODE_DS_BASE_INVALID);
10372 HMVMX_CHECK_BREAK((pCtx->es.Attr.u & X86DESCATTR_UNUSABLE) || !RT_HI_U32(pCtx->es.u64Base),
10373 VMX_IGS_LONGMODE_ES_BASE_INVALID);
10374#endif
10375 }
10376
10377 /*
10378 * TR.
10379 */
10380 HMVMX_CHECK_BREAK(!(pCtx->tr.Sel & X86_SEL_LDT), VMX_IGS_TR_TI_INVALID);
10381 /* 64-bit capable CPUs. */
10382#if HC_ARCH_BITS == 64
10383 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(pCtx->tr.u64Base), VMX_IGS_TR_BASE_NOT_CANONICAL);
10384#endif
10385 if (fLongModeGuest)
10386 {
10387 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u4Type == 11, /* 64-bit busy TSS. */
10388 VMX_IGS_LONGMODE_TR_ATTR_TYPE_INVALID);
10389 }
10390 else
10391 {
10392 HMVMX_CHECK_BREAK( pCtx->tr.Attr.n.u4Type == 3 /* 16-bit busy TSS. */
10393 || pCtx->tr.Attr.n.u4Type == 11, /* 32-bit busy TSS.*/
10394 VMX_IGS_TR_ATTR_TYPE_INVALID);
10395 }
10396 HMVMX_CHECK_BREAK(!pCtx->tr.Attr.n.u1DescType, VMX_IGS_TR_ATTR_S_INVALID);
10397 HMVMX_CHECK_BREAK(pCtx->tr.Attr.n.u1Present, VMX_IGS_TR_ATTR_P_INVALID);
10398 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & 0xf00), VMX_IGS_TR_ATTR_RESERVED); /* Bits 11:8 MBZ. */
10399 HMVMX_CHECK_BREAK( (pCtx->tr.u32Limit & 0xfff) == 0xfff
10400 || !(pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10401 HMVMX_CHECK_BREAK( !(pCtx->tr.u32Limit & 0xfff00000)
10402 || (pCtx->tr.Attr.n.u1Granularity), VMX_IGS_TR_ATTR_G_INVALID);
10403 HMVMX_CHECK_BREAK(!(pCtx->tr.Attr.u & X86DESCATTR_UNUSABLE), VMX_IGS_TR_ATTR_UNUSABLE);
10404
10405 /*
10406 * GDTR and IDTR.
10407 */
10408#if HC_ARCH_BITS == 64
10409 rc = VMXReadVmcs64(VMX_VMCS_GUEST_GDTR_BASE, &u64Val);
10410 AssertRCBreak(rc);
10411 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_GDTR_BASE_NOT_CANONICAL);
10412
10413 rc = VMXReadVmcs64(VMX_VMCS_GUEST_IDTR_BASE, &u64Val);
10414 AssertRCBreak(rc);
10415 HMVMX_CHECK_BREAK(X86_IS_CANONICAL(u64Val), VMX_IGS_IDTR_BASE_NOT_CANONICAL);
10416#endif
10417
10418 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_GDTR_LIMIT, &u32Val);
10419 AssertRCBreak(rc);
10420 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_GDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10421
10422 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_IDTR_LIMIT, &u32Val);
10423 AssertRCBreak(rc);
10424 HMVMX_CHECK_BREAK(!(u32Val & 0xffff0000), VMX_IGS_IDTR_LIMIT_INVALID); /* Bits 31:16 MBZ. */
10425
10426 /*
10427 * Guest Non-Register State.
10428 */
10429 /* Activity State. */
10430 uint32_t u32ActivityState;
10431 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_ACTIVITY_STATE, &u32ActivityState);
10432 AssertRCBreak(rc);
10433 HMVMX_CHECK_BREAK( !u32ActivityState
10434 || (u32ActivityState & RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Misc, VMX_BF_MISC_ACTIVITY_STATES)),
10435 VMX_IGS_ACTIVITY_STATE_INVALID);
10436 HMVMX_CHECK_BREAK( !(pCtx->ss.Attr.n.u2Dpl)
10437 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_HLT, VMX_IGS_ACTIVITY_STATE_HLT_INVALID);
10438 uint32_t u32IntrState;
10439 rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &u32IntrState);
10440 AssertRCBreak(rc);
10441 if ( u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS
10442 || u32IntrState == VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10443 {
10444 HMVMX_CHECK_BREAK(u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_ACTIVE, VMX_IGS_ACTIVITY_STATE_ACTIVE_INVALID);
10445 }
10446
10447 /** @todo Activity state and injecting interrupts. Left as a todo since we
10448 * currently don't use activity states but ACTIVE. */
10449
10450 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10451 || u32ActivityState != VMX_VMCS_GUEST_ACTIVITY_SIPI_WAIT, VMX_IGS_ACTIVITY_STATE_SIPI_WAIT_INVALID);
10452
10453 /* Guest interruptibility-state. */
10454 HMVMX_CHECK_BREAK(!(u32IntrState & 0xffffffe0), VMX_IGS_INTERRUPTIBILITY_STATE_RESERVED);
10455 HMVMX_CHECK_BREAK((u32IntrState & (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS))
10456 != (VMX_VMCS_GUEST_INT_STATE_BLOCK_STI | VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10457 VMX_IGS_INTERRUPTIBILITY_STATE_STI_MOVSS_INVALID);
10458 HMVMX_CHECK_BREAK( (u32Eflags & X86_EFL_IF)
10459 || !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10460 VMX_IGS_INTERRUPTIBILITY_STATE_STI_EFL_INVALID);
10461 if (VMX_ENTRY_INT_INFO_IS_EXT_INT(u32EntryInfo))
10462 {
10463 HMVMX_CHECK_BREAK( !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10464 && !(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10465 VMX_IGS_INTERRUPTIBILITY_STATE_EXT_INT_INVALID);
10466 }
10467 else if (VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10468 {
10469 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS),
10470 VMX_IGS_INTERRUPTIBILITY_STATE_MOVSS_INVALID);
10471 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI),
10472 VMX_IGS_INTERRUPTIBILITY_STATE_STI_INVALID);
10473 }
10474 /** @todo Assumes the processor is not in SMM. */
10475 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10476 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_INVALID);
10477 HMVMX_CHECK_BREAK( !(pVmcsInfo->u32EntryCtls & VMX_ENTRY_CTLS_ENTRY_TO_SMM)
10478 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_SMI),
10479 VMX_IGS_INTERRUPTIBILITY_STATE_SMI_SMM_INVALID);
10480 if ( (pVmcsInfo->u32PinCtls & VMX_PIN_CTLS_VIRT_NMI)
10481 && VMX_ENTRY_INT_INFO_IS_XCPT_NMI(u32EntryInfo))
10482 {
10483 HMVMX_CHECK_BREAK(!(u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_NMI),
10484 VMX_IGS_INTERRUPTIBILITY_STATE_NMI_INVALID);
10485 }
10486
10487 /* Pending debug exceptions. */
10488#if HC_ARCH_BITS == 64
10489 rc = VMXReadVmcs64(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u64Val);
10490 AssertRCBreak(rc);
10491 /* Bits 63:15, Bit 13, Bits 11:4 MBZ. */
10492 HMVMX_CHECK_BREAK(!(u64Val & UINT64_C(0xffffffffffffaff0)), VMX_IGS_LONGMODE_PENDING_DEBUG_RESERVED);
10493 u32Val = u64Val; /* For pending debug exceptions checks below. */
10494#else
10495 rc = VMXReadVmcs32(VMX_VMCS_GUEST_PENDING_DEBUG_XCPTS, &u32Val);
10496 AssertRCBreak(rc);
10497 /* Bits 31:15, Bit 13, Bits 11:4 MBZ. */
10498 HMVMX_CHECK_BREAK(!(u32Val & 0xffffaff0), VMX_IGS_PENDING_DEBUG_RESERVED);
10499#endif
10500
10501 if ( (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
10502 || (u32IntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS)
10503 || u32ActivityState == VMX_VMCS_GUEST_ACTIVITY_HLT)
10504 {
10505 if ( (u32Eflags & X86_EFL_TF)
10506 && !(u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10507 {
10508 /* Bit 14 is PendingDebug.BS. */
10509 HMVMX_CHECK_BREAK(u32Val & RT_BIT(14), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_SET);
10510 }
10511 if ( !(u32Eflags & X86_EFL_TF)
10512 || (u64DebugCtlMsr & RT_BIT_64(1))) /* Bit 1 is IA32_DEBUGCTL.BTF. */
10513 {
10514 /* Bit 14 is PendingDebug.BS. */
10515 HMVMX_CHECK_BREAK(!(u32Val & RT_BIT(14)), VMX_IGS_PENDING_DEBUG_XCPT_BS_NOT_CLEAR);
10516 }
10517 }
10518
10519 /* VMCS link pointer. */
10520 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_VMCS_LINK_PTR_FULL, &u64Val);
10521 AssertRCBreak(rc);
10522 if (u64Val != UINT64_C(0xffffffffffffffff))
10523 {
10524 HMVMX_CHECK_BREAK(!(u64Val & 0xfff), VMX_IGS_VMCS_LINK_PTR_RESERVED);
10525 /** @todo Bits beyond the processor's physical-address width MBZ. */
10526 /** @todo SMM checks. */
10527 Assert(pVmcsInfo->HCPhysShadowVmcs == u64Val);
10528 Assert(pVmcsInfo->pvShadowVmcs);
10529 VMXVMCSREVID VmcsRevId;
10530 VmcsRevId.u = *(uint32_t *)pVmcsInfo->pvShadowVmcs;
10531 HMVMX_CHECK_BREAK(VmcsRevId.n.u31RevisionId == RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_ID),
10532 VMX_IGS_VMCS_LINK_PTR_SHADOW_VMCS_ID_INVALID);
10533 HMVMX_CHECK_BREAK(VmcsRevId.n.fIsShadowVmcs == (uint32_t)!!(pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING),
10534 VMX_IGS_VMCS_LINK_PTR_NOT_SHADOW);
10535 }
10536
10537 /** @todo Checks on Guest Page-Directory-Pointer-Table Entries when guest is
10538 * not using nested paging? */
10539 if ( pVM->hm.s.fNestedPaging
10540 && !fLongModeGuest
10541 && CPUMIsGuestInPAEModeEx(pCtx))
10542 {
10543 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE0_FULL, &u64Val);
10544 AssertRCBreak(rc);
10545 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10546
10547 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE1_FULL, &u64Val);
10548 AssertRCBreak(rc);
10549 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10550
10551 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE2_FULL, &u64Val);
10552 AssertRCBreak(rc);
10553 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10554
10555 rc = VMXReadVmcs64(VMX_VMCS64_GUEST_PDPTE3_FULL, &u64Val);
10556 AssertRCBreak(rc);
10557 HMVMX_CHECK_BREAK(!(u64Val & X86_PDPE_PAE_MBZ_MASK), VMX_IGS_PAE_PDPTE_RESERVED);
10558 }
10559
10560 /* Shouldn't happen but distinguish it from AssertRCBreak() errors. */
10561 if (uError == VMX_IGS_ERROR)
10562 uError = VMX_IGS_REASON_NOT_FOUND;
10563 } while (0);
10564
10565 pVCpu->hm.s.u32HMError = uError;
10566 return uError;
10567
10568#undef HMVMX_ERROR_BREAK
10569#undef HMVMX_CHECK_BREAK
10570}
10571
10572
10573/**
10574 * Map the APIC-access page for virtualizing APIC accesses.
10575 *
10576 * This can cause a longjumps to R3 due to the acquisition of the PGM lock. Hence,
10577 * this not done as part of exporting guest state, see @bugref{8721}.
10578 *
10579 * @returns VBox status code.
10580 * @param pVCpu The cross context virtual CPU structure.
10581 */
10582static int hmR0VmxMapHCApicAccessPage(PVMCPU pVCpu)
10583{
10584 PVM pVM = pVCpu->CTX_SUFF(pVM);
10585 uint64_t const u64MsrApicBase = APICGetBaseMsrNoCheck(pVCpu);
10586
10587 Assert(PDMHasApic(pVM));
10588 Assert(u64MsrApicBase);
10589
10590 RTGCPHYS const GCPhysApicBase = u64MsrApicBase & PAGE_BASE_GC_MASK;
10591 Log4Func(("Mappping HC APIC-access page at %#RGp\n", GCPhysApicBase));
10592
10593 /* Unalias the existing mapping. */
10594 int rc = PGMHandlerPhysicalReset(pVM, GCPhysApicBase);
10595 AssertRCReturn(rc, rc);
10596
10597 /* Map the HC APIC-access page in place of the MMIO page, also updates the shadow page tables if necessary. */
10598 Assert(pVM->hm.s.vmx.HCPhysApicAccess != NIL_RTHCPHYS);
10599 rc = IOMMMIOMapMMIOHCPage(pVM, pVCpu, GCPhysApicBase, pVM->hm.s.vmx.HCPhysApicAccess, X86_PTE_RW | X86_PTE_P);
10600 AssertRCReturn(rc, rc);
10601
10602 /* Update the per-VCPU cache of the APIC base MSR. */
10603 pVCpu->hm.s.vmx.u64GstMsrApicBase = u64MsrApicBase;
10604 return VINF_SUCCESS;
10605}
10606
10607
10608/**
10609 * Worker function passed to RTMpOnSpecific() that is to be called on the target
10610 * CPU.
10611 *
10612 * @param idCpu The ID for the CPU the function is called on.
10613 * @param pvUser1 Null, not used.
10614 * @param pvUser2 Null, not used.
10615 */
10616static DECLCALLBACK(void) hmR0DispatchHostNmi(RTCPUID idCpu, void *pvUser1, void *pvUser2)
10617{
10618 RT_NOREF3(idCpu, pvUser1, pvUser2);
10619 VMXDispatchHostNmi();
10620}
10621
10622
10623/**
10624 * Dispatching an NMI on the host CPU that received it.
10625 *
10626 * @returns VBox status code.
10627 * @param pVCpu The cross context virtual CPU structure.
10628 * @param pVmcsInfo The VMCS info. object corresponding to the VMCS that was
10629 * executing when receiving the host NMI in VMX non-root
10630 * operation.
10631 */
10632static int hmR0VmxExitHostNmi(PVMCPU pVCpu, PCVMXVMCSINFO pVmcsInfo)
10633{
10634 RTCPUID const idCpu = pVmcsInfo->idHostCpu;
10635
10636 /*
10637 * We don't want to delay dispatching the NMI any more than we have to. However,
10638 * we have already chosen -not- to dispatch NMIs when interrupts were still disabled
10639 * after executing guest or nested-guest code for the following reasons:
10640 *
10641 * - We would need to perform VMREADs with interrupts disabled and is orders of
10642 * magnitude worse when we run as a guest hypervisor without VMCS shadowing
10643 * supported by the host hypervisor.
10644 *
10645 * - It affects the common VM-exit scenario and keeps interrupts disabled for a
10646 * longer period of time just for handling an edge case like host NMIs which do
10647 * not occur nearly as frequently as other VM-exits.
10648 *
10649 * Let's cover the most likely scenario first. Check if we are on the target CPU
10650 * and dispatch the NMI right away. This should be much faster than calling into
10651 * RTMpOnSpecific() machinery.
10652 */
10653 bool fDispatched = false;
10654 RTCCUINTREG const fEFlags = ASMIntDisableFlags();
10655 if (idCpu == RTMpCpuId())
10656 {
10657 VMXDispatchHostNmi();
10658 fDispatched = true;
10659 }
10660 ASMSetFlags(fEFlags);
10661 if (fDispatched)
10662 {
10663 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGC);
10664 return VINF_SUCCESS;
10665 }
10666
10667 /*
10668 * RTMpOnSpecific() waits until the worker function has run on the target CPU. So
10669 * there should be no race or recursion even if we are unlucky enough to be preempted
10670 * (to the target CPU) without dispatching the host NMI above.
10671 */
10672 STAM_REL_COUNTER_INC(&pVCpu->hm.s.StatExitHostNmiInGCIpi);
10673 return RTMpOnSpecific(idCpu, &hmR0DispatchHostNmi, NULL /* pvUser1 */, NULL /* pvUser2 */);
10674}
10675
10676
10677#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
10678/**
10679 * Merges the guest with the nested-guest MSR bitmap in preparation of executing the
10680 * nested-guest using hardware-assisted VMX.
10681 *
10682 * @param pVCpu The cross context virtual CPU structure.
10683 * @param pVmcsInfoNstGst The nested-guest VMCS info. object.
10684 * @param pVmcsInfoGst The guest VMCS info. object.
10685 */
10686static void hmR0VmxMergeMsrBitmapNested(PCVMCPU pVCpu, PVMXVMCSINFO pVmcsInfoNstGst, PCVMXVMCSINFO pVmcsInfoGst)
10687{
10688 uint32_t const cbMsrBitmap = X86_PAGE_4K_SIZE;
10689 uint64_t *pu64MsrBitmap = (uint64_t *)pVmcsInfoNstGst->pvMsrBitmap;
10690 Assert(pu64MsrBitmap);
10691
10692 /*
10693 * We merge the guest MSR bitmap with the nested-guest MSR bitmap such that any
10694 * MSR that is intercepted by the guest is also intercepted while executing the
10695 * nested-guest using hardware-assisted VMX.
10696 *
10697 * Note! If the nested-guest is not using an MSR bitmap, ever MSR must cause a
10698 * nested-guest VM-exit even if the outer guest is not intercepting some
10699 * MSRs. We cannot assume the caller has initialized the nested-guest
10700 * MSR bitmap in this case.
10701 *
10702 * The guest hypervisor may also switch whether it uses MSR bitmaps for
10703 * each VM-entry, hence initializing it once per-VM while setting up the
10704 * nested-guest VMCS is not sufficient.
10705 */
10706 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10707 if (pVmcsNstGst->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10708 {
10709 uint64_t const *pu64MsrBitmapNstGst = (uint64_t const *)pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap);
10710 uint64_t const *pu64MsrBitmapGst = (uint64_t const *)pVmcsInfoGst->pvMsrBitmap;
10711 Assert(pu64MsrBitmapNstGst);
10712 Assert(pu64MsrBitmapGst);
10713
10714 uint32_t const cFrags = cbMsrBitmap / sizeof(uint64_t);
10715 for (uint32_t i = 0; i < cFrags; i++)
10716 pu64MsrBitmap[i] = pu64MsrBitmapNstGst[i] | pu64MsrBitmapGst[i];
10717 }
10718 else
10719 ASMMemFill32(pu64MsrBitmap, cbMsrBitmap, UINT32_C(0xffffffff));
10720}
10721
10722
10723/**
10724 * Merges the guest VMCS in to the nested-guest VMCS controls in preparation of
10725 * hardware-assisted VMX execution of the nested-guest.
10726 *
10727 * For a guest, we don't modify these controls once we set up the VMCS and hence
10728 * this function is never called.
10729 *
10730 * For nested-guests since the guest hypervisor provides these controls on every
10731 * nested-guest VM-entry and could potentially change them everytime we need to
10732 * merge them before every nested-guest VM-entry.
10733 *
10734 * @returns VBox status code.
10735 * @param pVCpu The cross context virtual CPU structure.
10736 */
10737static int hmR0VmxMergeVmcsNested(PVMCPU pVCpu)
10738{
10739 PVM pVM = pVCpu->CTX_SUFF(pVM);
10740 PCVMXVMCSINFO pVmcsInfoGst = &pVCpu->hm.s.vmx.VmcsInfo;
10741 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
10742 Assert(pVmcsNstGst);
10743
10744 /*
10745 * Merge the controls with the requirements of the guest VMCS.
10746 *
10747 * We do not need to validate the nested-guest VMX features specified in the nested-guest
10748 * VMCS with the features supported by the physical CPU as it's already done by the
10749 * VMLAUNCH/VMRESUME instruction emulation.
10750 *
10751 * This is because the VMX features exposed by CPUM (through CPUID/MSRs) to the guest are
10752 * derived from the VMX features supported by the physical CPU.
10753 */
10754
10755 /* Pin-based VM-execution controls. */
10756 uint32_t const u32PinCtls = pVmcsNstGst->u32PinCtls | pVmcsInfoGst->u32PinCtls;
10757
10758 /* Processor-based VM-execution controls. */
10759 uint32_t u32ProcCtls = (pVmcsNstGst->u32ProcCtls & ~VMX_PROC_CTLS_USE_IO_BITMAPS)
10760 | (pVmcsInfoGst->u32ProcCtls & ~( VMX_PROC_CTLS_INT_WINDOW_EXIT
10761 | VMX_PROC_CTLS_NMI_WINDOW_EXIT
10762 | VMX_PROC_CTLS_USE_TPR_SHADOW
10763 | VMX_PROC_CTLS_MONITOR_TRAP_FLAG));
10764
10765 /* Secondary processor-based VM-execution controls. */
10766 uint32_t const u32ProcCtls2 = (pVmcsNstGst->u32ProcCtls2 & ~VMX_PROC_CTLS2_VPID)
10767 | (pVmcsInfoGst->u32ProcCtls2 & ~( VMX_PROC_CTLS2_VIRT_APIC_ACCESS
10768 | VMX_PROC_CTLS2_INVPCID
10769 | VMX_PROC_CTLS2_VMCS_SHADOWING
10770 | VMX_PROC_CTLS2_RDTSCP
10771 | VMX_PROC_CTLS2_XSAVES_XRSTORS
10772 | VMX_PROC_CTLS2_APIC_REG_VIRT
10773 | VMX_PROC_CTLS2_VIRT_INT_DELIVERY
10774 | VMX_PROC_CTLS2_VMFUNC));
10775
10776 /*
10777 * VM-entry controls:
10778 * These controls contains state that depends on the nested-guest state (primarily
10779 * EFER MSR) and is thus not constant between VMLAUNCH/VMRESUME and the nested-guest
10780 * VM-exit. Although the guest hypervisor cannot change it, we need to in order to
10781 * properly continue executing the nested-guest if the EFER MSR changes but does not
10782 * cause a nested-guest VM-exits.
10783 *
10784 * VM-exit controls:
10785 * These controls specify the host state on return. We cannot use the controls from
10786 * the guest hypervisor state as is as it would contain the guest state rather than
10787 * the host state. Since the host state is subject to change (e.g. preemption, trips
10788 * to ring-3, longjmp and rescheduling to a different host CPU) they are not constant
10789 * through VMLAUNCH/VMRESUME and the nested-guest VM-exit.
10790 *
10791 * VM-entry MSR-load:
10792 * The guest MSRs from the VM-entry MSR-load area are already loaded into the guest-CPU
10793 * context by the VMLAUNCH/VMRESUME instruction emulation.
10794 *
10795 * VM-exit MSR-store:
10796 * The VM-exit emulation will take care of populating the MSRs from the guest-CPU context
10797 * back into the VM-exit MSR-store area.
10798 *
10799 * VM-exit MSR-load areas:
10800 * This must contain the real host MSRs with hardware-assisted VMX execution. Hence, we
10801 * can entirely ignore what the guest hypervisor wants to load here.
10802 */
10803
10804 /*
10805 * Exception bitmap.
10806 *
10807 * We could remove #UD from the guest bitmap and merge it with the nested-guest bitmap
10808 * here (and avoid doing anything while exporting nested-guest state), but to keep the
10809 * code more flexible if intercepting exceptions become more dynamic in the future we do
10810 * it as part of exporting the nested-guest state.
10811 */
10812 uint32_t const u32XcptBitmap = pVmcsNstGst->u32XcptBitmap | pVmcsInfoGst->u32XcptBitmap;
10813
10814 /*
10815 * CR0/CR4 guest/host mask.
10816 *
10817 * Modifications by the nested-guest to CR0/CR4 bits owned by the host and the guest must
10818 * cause VM-exits, so we need to merge them here.
10819 */
10820 uint64_t const u64Cr0Mask = pVmcsNstGst->u64Cr0Mask.u | pVmcsInfoGst->u64Cr0Mask;
10821 uint64_t const u64Cr4Mask = pVmcsNstGst->u64Cr4Mask.u | pVmcsInfoGst->u64Cr4Mask;
10822
10823 /*
10824 * Page-fault error-code mask and match.
10825 *
10826 * Although we require unrestricted guest execution (and thereby nested-paging) for
10827 * hardware-assisted VMX execution of nested-guests and thus the outer guest doesn't
10828 * normally intercept #PFs, it might intercept them for debugging purposes.
10829 *
10830 * If the outer guest is not intercepting #PFs, we can use the nested-guest #PF filters.
10831 * If the outer guest is intercepting #PFs, we must intercept all #PFs.
10832 */
10833 uint32_t u32XcptPFMask;
10834 uint32_t u32XcptPFMatch;
10835 if (!(pVmcsInfoGst->u32XcptBitmap & RT_BIT(X86_XCPT_PF)))
10836 {
10837 u32XcptPFMask = pVmcsNstGst->u32XcptPFMask;
10838 u32XcptPFMatch = pVmcsNstGst->u32XcptPFMatch;
10839 }
10840 else
10841 {
10842 u32XcptPFMask = 0;
10843 u32XcptPFMatch = 0;
10844 }
10845
10846 /*
10847 * Pause-Loop exiting.
10848 */
10849 uint32_t const cPleGapTicks = RT_MIN(pVM->hm.s.vmx.cPleGapTicks, pVmcsNstGst->u32PleGap);
10850 uint32_t const cPleWindowTicks = RT_MIN(pVM->hm.s.vmx.cPleWindowTicks, pVmcsNstGst->u32PleWindow);
10851
10852 /*
10853 * I/O Bitmap.
10854 *
10855 * We do not use the I/O bitmap that may be provided by the guest hypervisor as we always
10856 * intercept all I/O port accesses.
10857 */
10858 Assert(u32ProcCtls & VMX_PROC_CTLS_UNCOND_IO_EXIT);
10859
10860 /*
10861 * VMCS shadowing.
10862 *
10863 * We do not yet expose VMCS shadowing to the guest and thus VMCS shadowing should not be
10864 * enabled while executing the nested-guest.
10865 */
10866 Assert(!(u32ProcCtls2 & VMX_PROC_CTLS2_VMCS_SHADOWING));
10867
10868 /*
10869 * APIC-access page.
10870 *
10871 * The APIC-access page address has already been initialized while setting up the
10872 * nested-guest VMCS. In theory, even if the guest-physical address is invalid, it should
10873 * not be of any consequence to the host or to the guest for that matter, but we only
10874 * accept valid addresses verified by the VMLAUNCH/VMRESUME instruction emulation to keep
10875 * it simple.
10876 */
10877
10878 /*
10879 * Virtual-APIC page and TPR threshold.
10880 *
10881 * The virtual-APIC page has already been allocated (by CPUM during VM startup) and cached
10882 * from guest memory as part of VMLAUNCH/VMRESUME instruction emulation. The host physical
10883 * address has also been updated in the nested-guest VMCS.
10884 */
10885 PVMXVMCSINFO pVmcsInfoNstGst = &pVCpu->hm.s.vmx.VmcsInfoNstGst;
10886 RTHCPHYS HCPhysVirtApic;
10887 uint32_t u32TprThreshold;
10888 if (u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
10889 {
10890 HCPhysVirtApic = pVmcsInfoNstGst->HCPhysVirtApic;
10891 u32TprThreshold = pVmcsNstGst->u32TprThreshold;
10892 }
10893 else
10894 {
10895 HCPhysVirtApic = 0;
10896 u32TprThreshold = 0;
10897
10898 /*
10899 * We must make sure CR8 reads/write must cause VM-exits when TPR shadowing is not
10900 * used by the guest hypervisor. Preventing MMIO accesses to the physical APIC will
10901 * be taken care of by EPT/shadow paging.
10902 */
10903 if (pVM->hm.s.fAllow64BitGuests)
10904 {
10905 u32ProcCtls |= VMX_PROC_CTLS_CR8_STORE_EXIT
10906 | VMX_PROC_CTLS_CR8_LOAD_EXIT;
10907 }
10908 }
10909
10910 /*
10911 * Validate basic assumptions.
10912 */
10913 Assert(pVM->hm.s.vmx.fAllowUnrestricted);
10914 Assert(pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1 & VMX_PROC_CTLS_USE_SECONDARY_CTLS);
10915 Assert(hmGetVmxActiveVmcsInfo(pVCpu) == pVmcsInfoNstGst);
10916
10917 /*
10918 * Commit it to the nested-guest VMCS.
10919 */
10920 int rc = VINF_SUCCESS;
10921 if (pVmcsInfoNstGst->u32PinCtls != u32PinCtls)
10922 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PIN_EXEC, u32PinCtls);
10923 if (pVmcsInfoNstGst->u32ProcCtls != u32ProcCtls)
10924 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, u32ProcCtls);
10925 if (pVmcsInfoNstGst->u32ProcCtls2 != u32ProcCtls2)
10926 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, u32ProcCtls2);
10927 if (pVmcsInfoNstGst->u32XcptBitmap != u32XcptBitmap)
10928 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, u32XcptBitmap);
10929 if (pVmcsInfoNstGst->u64Cr0Mask != u64Cr0Mask)
10930 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, u64Cr0Mask);
10931 if (pVmcsInfoNstGst->u64Cr4Mask != u64Cr4Mask)
10932 rc |= VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, u64Cr4Mask);
10933 if (pVmcsInfoNstGst->u32XcptPFMask != u32XcptPFMask)
10934 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MASK, u32XcptPFMask);
10935 if (pVmcsInfoNstGst->u32XcptPFMatch != u32XcptPFMatch)
10936 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PAGEFAULT_ERROR_MATCH, u32XcptPFMatch);
10937 if ( !(u32ProcCtls & VMX_PROC_CTLS_PAUSE_EXIT)
10938 && (u32ProcCtls2 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
10939 {
10940 Assert(pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_PAUSE_LOOP_EXIT);
10941 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_GAP, cPleGapTicks);
10942 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_PLE_WINDOW, cPleWindowTicks);
10943 }
10944 rc |= VMXWriteVmcs32(VMX_VMCS32_CTRL_TPR_THRESHOLD, u32TprThreshold);
10945 rc |= VMXWriteVmcs64(VMX_VMCS64_CTRL_VIRT_APIC_PAGEADDR_FULL, pVmcsInfoNstGst->HCPhysVirtApic);
10946 AssertRCReturn(rc, rc);
10947
10948 /*
10949 * Update the nested-guest VMCS cache.
10950 */
10951 pVmcsInfoNstGst->u32PinCtls = u32PinCtls;
10952 pVmcsInfoNstGst->u32ProcCtls = u32ProcCtls;
10953 pVmcsInfoNstGst->u32ProcCtls2 = u32ProcCtls2;
10954 pVmcsInfoNstGst->u32XcptBitmap = u32XcptBitmap;
10955 pVmcsInfoNstGst->u64Cr0Mask = u64Cr0Mask;
10956 pVmcsInfoNstGst->u64Cr4Mask = u64Cr4Mask;
10957 pVmcsInfoNstGst->u32XcptPFMask = u32XcptPFMask;
10958 pVmcsInfoNstGst->u32XcptPFMatch = u32XcptPFMatch;
10959 pVmcsInfoNstGst->HCPhysVirtApic = HCPhysVirtApic;
10960
10961 /*
10962 * MSR bitmap.
10963 *
10964 * The MSR bitmap address has already been initialized while setting up the nested-guest
10965 * VMCS, here we need to merge the MSR bitmaps.
10966 */
10967 if (u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
10968 hmR0VmxMergeMsrBitmapNested(pVCpu, pVmcsInfoNstGst, pVmcsInfoGst);
10969
10970 return VINF_SUCCESS;
10971}
10972#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
10973
10974
10975/**
10976 * Does the preparations before executing guest code in VT-x.
10977 *
10978 * This may cause longjmps to ring-3 and may even result in rescheduling to the
10979 * recompiler/IEM. We must be cautious what we do here regarding committing
10980 * guest-state information into the VMCS assuming we assuredly execute the
10981 * guest in VT-x mode.
10982 *
10983 * If we fall back to the recompiler/IEM after updating the VMCS and clearing
10984 * the common-state (TRPM/forceflags), we must undo those changes so that the
10985 * recompiler/IEM can (and should) use them when it resumes guest execution.
10986 * Otherwise such operations must be done when we can no longer exit to ring-3.
10987 *
10988 * @returns Strict VBox status code (i.e. informational status codes too).
10989 * @retval VINF_SUCCESS if we can proceed with running the guest, interrupts
10990 * have been disabled.
10991 * @retval VINF_VMX_VMEXIT if a nested-guest VM-exit occurs (e.g., while evaluating
10992 * pending events).
10993 * @retval VINF_EM_RESET if a triple-fault occurs while injecting a
10994 * double-fault into the guest.
10995 * @retval VINF_EM_DBG_STEPPED if @a fStepping is true and an event was
10996 * dispatched directly.
10997 * @retval VINF_* scheduling changes, we have to go back to ring-3.
10998 *
10999 * @param pVCpu The cross context virtual CPU structure.
11000 * @param pVmxTransient The VMX-transient structure.
11001 * @param fStepping Whether we are single-stepping the guest in the
11002 * hypervisor debugger. Makes us ignore some of the reasons
11003 * for returning to ring-3, and return VINF_EM_DBG_STEPPED
11004 * if event dispatching took place.
11005 */
11006static VBOXSTRICTRC hmR0VmxPreRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, bool fStepping)
11007{
11008 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11009
11010#ifdef VBOX_WITH_NESTED_HWVIRT_ONLY_IN_IEM
11011 if (pVmxTransient->fIsNestedGuest)
11012 {
11013 RT_NOREF2(pVCpu, fStepping);
11014 Log2Func(("Rescheduling to IEM due to nested-hwvirt or forced IEM exec -> VINF_EM_RESCHEDULE_REM\n"));
11015 return VINF_EM_RESCHEDULE_REM;
11016 }
11017#endif
11018
11019#ifdef VBOX_WITH_2X_4GB_ADDR_SPACE_IN_R0
11020 PGMRZDynMapFlushAutoSet(pVCpu);
11021#endif
11022
11023 /*
11024 * Check and process force flag actions, some of which might require us to go back to ring-3.
11025 */
11026 VBOXSTRICTRC rcStrict = hmR0VmxCheckForceFlags(pVCpu, fStepping);
11027 if (rcStrict == VINF_SUCCESS)
11028 { /* FFs don't get set all the time. */ }
11029 else
11030 return rcStrict;
11031
11032 /*
11033 * Virtualize memory-mapped accesses to the physical APIC (may take locks).
11034 */
11035 /** @todo Doing this from ring-3 after VM setup phase causes a
11036 * VERR_IOM_MMIO_RANGE_NOT_FOUND guru while booting Visa 64 SMP VM. No
11037 * idea why atm. */
11038 PVM pVM = pVCpu->CTX_SUFF(pVM);
11039 if ( !pVCpu->hm.s.vmx.u64GstMsrApicBase
11040 && (pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1 & VMX_PROC_CTLS2_VIRT_APIC_ACCESS)
11041 && PDMHasApic(pVM))
11042 {
11043 int rc = hmR0VmxMapHCApicAccessPage(pVCpu);
11044 AssertRCReturn(rc, rc);
11045 }
11046
11047#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11048 /*
11049 * Merge guest VMCS controls with the nested-guest VMCS controls.
11050 *
11051 * Even if we have not executed the guest prior to this (e.g. when resuming from a
11052 * saved state), we should be okay with merging controls as we initialize the
11053 * guest VMCS controls as part of VM setup phase.
11054 */
11055 if ( pVmxTransient->fIsNestedGuest
11056 && !pVCpu->hm.s.vmx.fMergedNstGstCtls)
11057 {
11058 int rc = hmR0VmxMergeVmcsNested(pVCpu);
11059 AssertRCReturn(rc, rc);
11060 pVCpu->hm.s.vmx.fMergedNstGstCtls = true;
11061 }
11062#endif
11063
11064 /*
11065 * Evaluate events to be injected into the guest.
11066 *
11067 * Events in TRPM can be injected without inspecting the guest state.
11068 * If any new events (interrupts/NMI) are pending currently, we try to set up the
11069 * guest to cause a VM-exit the next time they are ready to receive the event.
11070 *
11071 * With nested-guests, evaluating pending events may cause VM-exits.
11072 */
11073 if (TRPMHasTrap(pVCpu))
11074 hmR0VmxTrpmTrapToPendingEvent(pVCpu);
11075
11076 uint32_t fIntrState;
11077 rcStrict = hmR0VmxEvaluatePendingEvent(pVCpu, pVmxTransient, &fIntrState);
11078
11079#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11080 /*
11081 * While evaluating pending events if something failed (unlikely) or if we were
11082 * preparing to run a nested-guest but performed a nested-guest VM-exit, we should bail.
11083 */
11084 if (rcStrict != VINF_SUCCESS)
11085 return rcStrict;
11086 if ( pVmxTransient->fIsNestedGuest
11087 && !CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11088 {
11089 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11090 return VINF_VMX_VMEXIT;
11091 }
11092#else
11093 Assert(rcStrict == VINF_SUCCESS);
11094#endif
11095
11096 /*
11097 * Event injection may take locks (currently the PGM lock for real-on-v86 case) and thus
11098 * needs to be done with longjmps or interrupts + preemption enabled. Event injection might
11099 * also result in triple-faulting the VM.
11100 *
11101 * With nested-guests, the above does not apply since unrestricted guest execution is a
11102 * requirement. Regardless, we do this here to avoid duplicating code elsewhere.
11103 */
11104 rcStrict = hmR0VmxInjectPendingEvent(pVCpu, pVmxTransient, fIntrState, fStepping);
11105 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11106 { /* likely */ }
11107 else
11108 {
11109 AssertMsg(rcStrict == VINF_EM_RESET || (rcStrict == VINF_EM_DBG_STEPPED && fStepping),
11110 ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
11111 return rcStrict;
11112 }
11113
11114 /*
11115 * A longjump might result in importing CR3 even for VM-exits that don't necessarily
11116 * import CR3 themselves. We will need to update them here, as even as late as the above
11117 * hmR0VmxInjectPendingEvent() call may lazily import guest-CPU state on demand causing
11118 * the below force flags to be set.
11119 */
11120 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3))
11121 {
11122 Assert(!(ASMAtomicUoReadU64(&pVCpu->cpum.GstCtx.fExtrn) & CPUMCTX_EXTRN_CR3));
11123 int rc2 = PGMUpdateCR3(pVCpu, CPUMGetGuestCR3(pVCpu));
11124 AssertMsgReturn(rc2 == VINF_SUCCESS || rc2 == VINF_PGM_SYNC_CR3,
11125 ("%Rrc\n", rc2), RT_FAILURE_NP(rc2) ? rc2 : VERR_IPE_UNEXPECTED_INFO_STATUS);
11126 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11127 }
11128 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES))
11129 {
11130 PGMGstUpdatePaePdpes(pVCpu, &pVCpu->hm.s.aPdpes[0]);
11131 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11132 }
11133
11134#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11135 /* Paranoia. */
11136 Assert(!pVmxTransient->fIsNestedGuest || CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11137#endif
11138
11139 /*
11140 * No longjmps to ring-3 from this point on!!!
11141 * Asserts() will still longjmp to ring-3 (but won't return), which is intentional, better than a kernel panic.
11142 * This also disables flushing of the R0-logger instance (if any).
11143 */
11144 VMMRZCallRing3Disable(pVCpu);
11145
11146 /*
11147 * Export the guest state bits.
11148 *
11149 * We cannot perform longjmps while loading the guest state because we do not preserve the
11150 * host/guest state (although the VMCS will be preserved) across longjmps which can cause
11151 * CPU migration.
11152 *
11153 * If we are injecting events to a real-on-v86 mode guest, we would have updated RIP and some segment
11154 * registers. Hence, exporting of the guest state needs to be done -after- injection of events.
11155 */
11156 rcStrict = hmR0VmxExportGuestStateOptimal(pVCpu, pVmxTransient);
11157 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
11158 { /* likely */ }
11159 else
11160 {
11161 VMMRZCallRing3Enable(pVCpu);
11162 return rcStrict;
11163 }
11164
11165 /*
11166 * We disable interrupts so that we don't miss any interrupts that would flag preemption
11167 * (IPI/timers etc.) when thread-context hooks aren't used and we've been running with
11168 * preemption disabled for a while. Since this is purely to aid the
11169 * RTThreadPreemptIsPending() code, it doesn't matter that it may temporarily reenable and
11170 * disable interrupt on NT.
11171 *
11172 * We need to check for force-flags that could've possible been altered since we last
11173 * checked them (e.g. by PDMGetInterrupt() leaving the PDM critical section,
11174 * see @bugref{6398}).
11175 *
11176 * We also check a couple of other force-flags as a last opportunity to get the EMT back
11177 * to ring-3 before executing guest code.
11178 */
11179 pVmxTransient->fEFlags = ASMIntDisableFlags();
11180
11181 if ( ( !VM_FF_IS_ANY_SET(pVM, VM_FF_EMT_RENDEZVOUS | VM_FF_TM_VIRTUAL_SYNC)
11182 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK))
11183 || ( fStepping /* Optimized for the non-stepping case, so a bit of unnecessary work when stepping. */
11184 && !VMCPU_FF_IS_ANY_SET(pVCpu, VMCPU_FF_HM_TO_R3_MASK & ~(VMCPU_FF_TIMER | VMCPU_FF_PDM_CRITSECT))) )
11185 {
11186 if (!RTThreadPreemptIsPending(NIL_RTTHREAD))
11187 {
11188#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11189 /*
11190 * If we are executing a nested-guest make sure that we should intercept subsequent
11191 * events. The one we are injecting might be part of VM-entry. This is mainly to keep
11192 * the VM-exit instruction emulation happy.
11193 */
11194 if (pVmxTransient->fIsNestedGuest)
11195 pVCpu->cpum.GstCtx.hwvirt.vmx.fInterceptEvents = true;
11196#endif
11197
11198 /*
11199 * We've injected any pending events. This is really the point of no return (to ring-3).
11200 *
11201 * Note! The caller expects to continue with interrupts & longjmps disabled on successful
11202 * returns from this function, so do -not- enable them here.
11203 */
11204 pVCpu->hm.s.Event.fPending = false;
11205 return VINF_SUCCESS;
11206 }
11207
11208 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchPendingHostIrq);
11209 rcStrict = VINF_EM_RAW_INTERRUPT;
11210 }
11211 else
11212 {
11213 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHmToR3FF);
11214 rcStrict = VINF_EM_RAW_TO_R3;
11215 }
11216
11217 ASMSetFlags(pVmxTransient->fEFlags);
11218 VMMRZCallRing3Enable(pVCpu);
11219
11220 return rcStrict;
11221}
11222
11223
11224/**
11225 * Final preparations before executing guest code using hardware-assisted VMX.
11226 *
11227 * We can no longer get preempted to a different host CPU and there are no returns
11228 * to ring-3. We ignore any errors that may happen from this point (e.g. VMWRITE
11229 * failures), this function is not intended to fail sans unrecoverable hardware
11230 * errors.
11231 *
11232 * @param pVCpu The cross context virtual CPU structure.
11233 * @param pVmxTransient The VMX-transient structure.
11234 *
11235 * @remarks Called with preemption disabled.
11236 * @remarks No-long-jump zone!!!
11237 */
11238static void hmR0VmxPreRunGuestCommitted(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
11239{
11240 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11241 Assert(VMMR0IsLogFlushDisabled(pVCpu));
11242 Assert(!RTThreadPreemptIsEnabled(NIL_RTTHREAD));
11243 Assert(!pVCpu->hm.s.Event.fPending);
11244
11245 /*
11246 * Indicate start of guest execution and where poking EMT out of guest-context is recognized.
11247 */
11248 VMCPU_ASSERT_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11249 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_EXEC);
11250
11251 PVM pVM = pVCpu->CTX_SUFF(pVM);
11252 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11253 PHMPHYSCPU pHostCpu = hmR0GetCurrentCpu();
11254 RTCPUID const idCurrentCpu = pHostCpu->idCpu;
11255
11256 if (!CPUMIsGuestFPUStateActive(pVCpu))
11257 {
11258 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11259 if (CPUMR0LoadGuestFPU(pVM, pVCpu) == VINF_CPUM_HOST_CR0_MODIFIED)
11260 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_HOST_CONTEXT;
11261 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatLoadGuestFpuState, x);
11262 STAM_COUNTER_INC(&pVCpu->hm.s.StatLoadGuestFpu);
11263 }
11264
11265 /*
11266 * Re-export the host state bits as we may've been preempted (only happens when
11267 * thread-context hooks are used or when the VM start function changes) or if
11268 * the host CR0 is modified while loading the guest FPU state above.
11269 *
11270 * The 64-on-32 switcher saves the (64-bit) host state into the VMCS and if we
11271 * changed the switcher back to 32-bit, we *must* save the 32-bit host state here,
11272 * see @bugref{8432}.
11273 *
11274 * This may also happen when switching to/from a nested-guest VMCS without leaving
11275 * ring-0.
11276 */
11277 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT)
11278 {
11279 hmR0VmxExportHostState(pVCpu);
11280 STAM_COUNTER_INC(&pVCpu->hm.s.StatExportHostState);
11281 }
11282 Assert(!(pVCpu->hm.s.fCtxChanged & HM_CHANGED_HOST_CONTEXT));
11283
11284 /*
11285 * Export the state shared between host and guest (FPU, debug, lazy MSRs).
11286 */
11287 if (pVCpu->hm.s.fCtxChanged & HM_CHANGED_VMX_HOST_GUEST_SHARED_STATE)
11288 hmR0VmxExportSharedState(pVCpu, pVmxTransient);
11289 AssertMsg(!pVCpu->hm.s.fCtxChanged, ("fCtxChanged=%#RX64\n", pVCpu->hm.s.fCtxChanged));
11290
11291 /*
11292 * Store status of the shared guest/host debug state at the time of VM-entry.
11293 */
11294#if HC_ARCH_BITS == 32 && defined(VBOX_WITH_64_BITS_GUESTS)
11295 if (CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
11296 {
11297 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActivePending(pVCpu);
11298 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActivePending(pVCpu);
11299 }
11300 else
11301#endif
11302 {
11303 pVmxTransient->fWasGuestDebugStateActive = CPUMIsGuestDebugStateActive(pVCpu);
11304 pVmxTransient->fWasHyperDebugStateActive = CPUMIsHyperDebugStateActive(pVCpu);
11305 }
11306
11307 /*
11308 * Always cache the TPR-shadow if the virtual-APIC page exists, thereby skipping
11309 * more than one conditional check. The post-run side of our code shall determine
11310 * if it needs to sync. the virtual APIC TPR with the TPR-shadow.
11311 */
11312 if (pVmcsInfo->pbVirtApic)
11313 pVmxTransient->u8GuestTpr = pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR];
11314
11315 /*
11316 * Update the host MSRs values in the VM-exit MSR-load area.
11317 */
11318 if (!pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs)
11319 {
11320 if (pVmcsInfo->cExitMsrLoad > 0)
11321 hmR0VmxUpdateAutoLoadHostMsrs(pVCpu, pVmcsInfo);
11322 pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs = true;
11323 }
11324
11325 /*
11326 * Evaluate if we need to intercept guest RDTSC/P accesses. Set up the
11327 * VMX-preemption timer based on the next virtual sync clock deadline.
11328 */
11329 if ( !pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer
11330 || idCurrentCpu != pVCpu->hm.s.idLastCpu)
11331 {
11332 hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu, pVmxTransient);
11333 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = true;
11334 }
11335
11336 /* Record statistics of how often we use TSC offsetting as opposed to intercepting RDTSC/P. */
11337 bool const fIsRdtscIntercepted = RT_BOOL(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT);
11338 if (!fIsRdtscIntercepted)
11339 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscOffset);
11340 else
11341 STAM_COUNTER_INC(&pVCpu->hm.s.StatTscIntercept);
11342
11343 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, true); /* Used for TLB flushing, set this across the world switch. */
11344 hmR0VmxFlushTaggedTlb(pHostCpu, pVCpu, pVmcsInfo); /* Invalidate the appropriate guest entries from the TLB. */
11345 Assert(idCurrentCpu == pVCpu->hm.s.idLastCpu);
11346 pVCpu->hm.s.vmx.LastError.idCurrentCpu = idCurrentCpu; /* Update the error reporting info. with the current host CPU. */
11347 pVmcsInfo->idHostCpu = idCurrentCpu; /* Update the CPU for which we updated host-state in this VMCS. */
11348
11349 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatEntry, &pVCpu->hm.s.StatInGC, x);
11350
11351 TMNotifyStartOfExecution(pVCpu); /* Notify TM to resume its clocks when TSC is tied to execution,
11352 as we're about to start executing the guest . */
11353
11354 /*
11355 * Load the guest TSC_AUX MSR when we are not intercepting RDTSCP.
11356 *
11357 * This is done this late as updating the TSC offsetting/preemption timer above
11358 * figures out if we can skip intercepting RDTSCP by calculating the number of
11359 * host CPU ticks till the next virtual sync deadline (for the dynamic case).
11360 */
11361 if ( (pVmcsInfo->u32ProcCtls2 & VMX_PROC_CTLS2_RDTSCP)
11362 && !fIsRdtscIntercepted)
11363 {
11364 hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_TSC_AUX);
11365
11366 /* NB: Because we call hmR0VmxAddAutoLoadStoreMsr with fUpdateHostMsr=true,
11367 it's safe even after hmR0VmxUpdateAutoLoadHostMsrs has already been done. */
11368 int rc = hmR0VmxAddAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX, CPUMGetGuestTscAux(pVCpu),
11369 true /* fSetReadWrite */, true /* fUpdateHostMsr */);
11370 AssertRC(rc);
11371 Assert(!pVmxTransient->fRemoveTscAuxMsr);
11372 pVmxTransient->fRemoveTscAuxMsr = true;
11373 }
11374
11375#ifdef VBOX_STRICT
11376 Assert(pVCpu->hm.s.vmx.fUpdatedHostAutoMsrs);
11377 hmR0VmxCheckAutoLoadStoreMsrs(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
11378 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo);
11379 AssertRC(hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest));
11380#endif
11381
11382#ifdef HMVMX_ALWAYS_CHECK_GUEST_STATE
11383 /** @todo r=ramshankar: We can now probably use iemVmxVmentryCheckGuestState here.
11384 * Add a PVMXMSRS parameter to it, so that IEM can look at the host MSRs,
11385 * see @bugref{9180#c54}. */
11386 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
11387 if (uInvalidReason != VMX_IGS_REASON_NOT_FOUND)
11388 Log4(("hmR0VmxCheckGuestState returned %#x\n", uInvalidReason));
11389#endif
11390}
11391
11392
11393/**
11394 * First C routine invoked after running guest code using hardware-assisted VMX.
11395 *
11396 * @param pVCpu The cross context virtual CPU structure.
11397 * @param pVmxTransient The VMX-transient structure.
11398 * @param rcVMRun Return code of VMLAUNCH/VMRESUME.
11399 *
11400 * @remarks Called with interrupts disabled, and returns with interrupts enabled!
11401 *
11402 * @remarks No-long-jump zone!!! This function will however re-enable longjmps
11403 * unconditionally when it is safe to do so.
11404 */
11405static void hmR0VmxPostRunGuest(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, int rcVMRun)
11406{
11407 uint64_t const uHostTsc = ASMReadTSC(); /** @todo We can do a lot better here, see @bugref{9180#c38}. */
11408
11409 ASMAtomicWriteBool(&pVCpu->hm.s.fCheckedTLBFlush, false); /* See HMInvalidatePageOnAllVCpus(): used for TLB flushing. */
11410 ASMAtomicIncU32(&pVCpu->hm.s.cWorldSwitchExits); /* Initialized in vmR3CreateUVM(): used for EMT poking. */
11411 pVCpu->hm.s.fCtxChanged = 0; /* Exits/longjmps to ring-3 requires saving the guest state. */
11412 pVmxTransient->fVmcsFieldsRead = 0; /* Transient fields need to be read from the VMCS. */
11413 pVmxTransient->fVectoringPF = false; /* Vectoring page-fault needs to be determined later. */
11414 pVmxTransient->fVectoringDoublePF = false; /* Vectoring double page-fault needs to be determined later. */
11415
11416 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11417 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_RDTSC_EXIT))
11418 {
11419 uint64_t uGstTsc;
11420 if (!pVmxTransient->fIsNestedGuest)
11421 uGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11422 else
11423 {
11424 uint64_t const uNstGstTsc = uHostTsc + pVmcsInfo->u64TscOffset;
11425 uGstTsc = CPUMRemoveNestedGuestTscOffset(pVCpu, uNstGstTsc);
11426 }
11427 TMCpuTickSetLastSeen(pVCpu, uGstTsc); /* Update TM with the guest TSC. */
11428 }
11429
11430 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatPreExit, x);
11431 TMNotifyEndOfExecution(pVCpu); /* Notify TM that the guest is no longer running. */
11432 VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED_HM);
11433
11434#if HC_ARCH_BITS == 64
11435 pVCpu->hm.s.vmx.fRestoreHostFlags |= VMX_RESTORE_HOST_REQUIRED; /* Some host state messed up by VMX needs restoring. */
11436#endif
11437#if HC_ARCH_BITS == 32 && defined(VBOX_ENABLE_64_BITS_GUESTS)
11438 /* The 64-on-32 switcher maintains VMCS-launch state on its own
11439 and we need to leave it alone here. */
11440 if (pVmcsInfo->pfnStartVM != VMXR0SwitcherStartVM64)
11441 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11442#else
11443 pVmcsInfo->fVmcsState |= VMX_V_VMCS_LAUNCH_STATE_LAUNCHED; /* Use VMRESUME instead of VMLAUNCH in the next run. */
11444#endif
11445#ifdef VBOX_STRICT
11446 hmR0VmxCheckHostEferMsr(pVCpu, pVmcsInfo); /* Verify that the host EFER MSR wasn't modified. */
11447#endif
11448 Assert(!ASMIntAreEnabled());
11449 ASMSetFlags(pVmxTransient->fEFlags); /* Enable interrupts. */
11450 Assert(!VMMRZCallRing3IsEnabled(pVCpu));
11451
11452#ifdef HMVMX_ALWAYS_CLEAN_TRANSIENT
11453 /*
11454 * Clean all the VMCS fields in the transient structure before reading
11455 * anything from the VMCS.
11456 */
11457 pVmxTransient->uExitReason = 0;
11458 pVmxTransient->uExitIntErrorCode = 0;
11459 pVmxTransient->uExitQual = 0;
11460 pVmxTransient->uGuestLinearAddr = 0;
11461 pVmxTransient->uExitIntInfo = 0;
11462 pVmxTransient->cbInstr = 0;
11463 pVmxTransient->ExitInstrInfo.u = 0;
11464 pVmxTransient->uEntryIntInfo = 0;
11465 pVmxTransient->uEntryXcptErrorCode = 0;
11466 pVmxTransient->cbEntryInstr = 0;
11467 pVmxTransient->uIdtVectoringInfo = 0;
11468 pVmxTransient->uIdtVectoringErrorCode = 0;
11469#endif
11470
11471 /*
11472 * Save the basic VM-exit reason and check if the VM-entry failed.
11473 * See Intel spec. 24.9.1 "Basic VM-exit Information".
11474 */
11475 uint32_t uExitReason;
11476 int rc = VMXReadVmcs32(VMX_VMCS32_RO_EXIT_REASON, &uExitReason);
11477 AssertRC(rc);
11478 pVmxTransient->uExitReason = VMX_EXIT_REASON_BASIC(uExitReason);
11479 pVmxTransient->fVMEntryFailed = VMX_EXIT_REASON_HAS_ENTRY_FAILED(uExitReason);
11480
11481 /*
11482 * Log the VM-exit before logging anything else as otherwise it might be a
11483 * tad confusing what happens before and after the world-switch.
11484 */
11485 HMVMX_LOG_EXIT(pVCpu, uExitReason);
11486
11487 /*
11488 * Remove the TSC_AUX MSR from the auto-load/store MSR area and reset any MSR
11489 * bitmap permissions, if it was added before VM-entry.
11490 */
11491 if (pVmxTransient->fRemoveTscAuxMsr)
11492 {
11493 hmR0VmxRemoveAutoLoadStoreMsr(pVCpu, pVmxTransient, MSR_K8_TSC_AUX);
11494 pVmxTransient->fRemoveTscAuxMsr = false;
11495 }
11496
11497 /*
11498 * Check if VMLAUNCH/VMRESUME succeeded.
11499 * If this failed, we cause a guru meditation and cease further execution.
11500 *
11501 * However, if we are executing a nested-guest we might fail if we use the
11502 * fast path rather than fully emulating VMLAUNCH/VMRESUME instruction in IEM.
11503 */
11504 if (RT_LIKELY(rcVMRun == VINF_SUCCESS))
11505 {
11506 /*
11507 * Update the VM-exit history array here even if the VM-entry failed due to:
11508 * - Invalid guest state.
11509 * - MSR loading.
11510 * - Machine-check event.
11511 *
11512 * In any of the above cases we will still have a "valid" VM-exit reason
11513 * despite @a fVMEntryFailed being false.
11514 *
11515 * See Intel spec. 26.7 "VM-Entry failures during or after loading guest state".
11516 *
11517 * Note! We don't have CS or RIP at this point. Will probably address that later
11518 * by amending the history entry added here.
11519 */
11520 EMHistoryAddExit(pVCpu, EMEXIT_MAKE_FT(EMEXIT_F_KIND_VMX, pVmxTransient->uExitReason & EMEXIT_F_TYPE_MASK),
11521 UINT64_MAX, uHostTsc);
11522
11523 if (RT_LIKELY(!pVmxTransient->fVMEntryFailed))
11524 {
11525 VMMRZCallRing3Enable(pVCpu);
11526
11527 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_CR3));
11528 Assert(!VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_HM_UPDATE_PAE_PDPES));
11529
11530#if defined(HMVMX_ALWAYS_SYNC_FULL_GUEST_STATE) || defined(HMVMX_ALWAYS_SAVE_FULL_GUEST_STATE)
11531 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
11532 AssertRC(rc);
11533#elif defined(HMVMX_ALWAYS_SAVE_GUEST_RFLAGS)
11534 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_RFLAGS);
11535 AssertRC(rc);
11536#else
11537 /*
11538 * Import the guest-interruptibility state always as we need it while evaluating
11539 * injecting events on re-entry.
11540 *
11541 * We don't import CR0 (when unrestricted guest execution is unavailable) despite
11542 * checking for real-mode while exporting the state because all bits that cause
11543 * mode changes wrt CR0 are intercepted.
11544 */
11545 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_HM_VMX_INT_STATE);
11546 AssertRC(rc);
11547#endif
11548
11549 /*
11550 * Sync the TPR shadow with our APIC state.
11551 *
11552 * With nested-guests, mark the virtual-APIC page as dirty so it can be synced
11553 * when performing the nested-guest VM-exit.
11554 */
11555 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
11556 {
11557 if (!pVmxTransient->fIsNestedGuest)
11558 {
11559 Assert(pVmcsInfo->pbVirtApic);
11560 if (pVmxTransient->u8GuestTpr != pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR])
11561 {
11562 rc = APICSetTpr(pVCpu, pVmcsInfo->pbVirtApic[XAPIC_OFF_TPR]);
11563 AssertRC(rc);
11564 ASMAtomicOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
11565 }
11566 }
11567 else
11568 pVCpu->cpum.GstCtx.hwvirt.vmx.fVirtApicPageDirty = true;
11569 }
11570
11571 Assert(VMMRZCallRing3IsEnabled(pVCpu));
11572 return;
11573 }
11574 }
11575#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11576 else if (pVmxTransient->fIsNestedGuest)
11577 AssertMsgFailed(("VMLAUNCH/VMRESUME failed but shouldn't happen when VMLAUNCH/VMRESUME was emulated in IEM!\n"));
11578#endif
11579 else
11580 Log4Func(("VM-entry failure: rcVMRun=%Rrc fVMEntryFailed=%RTbool\n", rcVMRun, pVmxTransient->fVMEntryFailed));
11581
11582 VMMRZCallRing3Enable(pVCpu);
11583}
11584
11585
11586/**
11587 * Runs the guest code using hardware-assisted VMX the normal way.
11588 *
11589 * @returns VBox status code.
11590 * @param pVCpu The cross context virtual CPU structure.
11591 * @param pcLoops Pointer to the number of executed loops.
11592 */
11593static VBOXSTRICTRC hmR0VmxRunGuestCodeNormal(PVMCPU pVCpu, uint32_t *pcLoops)
11594{
11595 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11596 Assert(pcLoops);
11597 Assert(*pcLoops <= cMaxResumeLoops);
11598 Assert(!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11599
11600#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11601 /*
11602 * Switch to the guest VMCS as we may have transitioned from executing the nested-guest
11603 * without leaving ring-0. Otherwise, if we came from ring-3 we would have loaded the
11604 * guest VMCS while entering the VMX ring-0 session.
11605 */
11606 if (pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11607 {
11608 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, false /* fSwitchToNstGstVmcs */);
11609 if (RT_SUCCESS(rc))
11610 { /* likely */ }
11611 else
11612 {
11613 LogRelFunc(("Failed to switch to the guest VMCS. rc=%Rrc\n", rc));
11614 return rc;
11615 }
11616 }
11617#endif
11618
11619 VMXTRANSIENT VmxTransient;
11620 RT_ZERO(VmxTransient);
11621 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11622
11623 /* Paranoia. */
11624 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfo);
11625
11626 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11627 for (;;)
11628 {
11629 Assert(!HMR0SuspendPending());
11630 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11631 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11632
11633 /*
11634 * Preparatory work for running nested-guest code, this may force us to
11635 * return to ring-3.
11636 *
11637 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11638 */
11639 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11640 if (rcStrict != VINF_SUCCESS)
11641 break;
11642
11643 /* Interrupts are disabled at this point! */
11644 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11645 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11646 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11647 /* Interrupts are re-enabled at this point! */
11648
11649 /*
11650 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11651 */
11652 if (RT_SUCCESS(rcRun))
11653 { /* very likely */ }
11654 else
11655 {
11656 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11657 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11658 return rcRun;
11659 }
11660
11661 /*
11662 * Profile the VM-exit.
11663 */
11664 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11665 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11666 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11667 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11668 HMVMX_START_EXIT_DISPATCH_PROF();
11669
11670 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11671
11672 /*
11673 * Handle the VM-exit.
11674 */
11675#ifdef HMVMX_USE_FUNCTION_TABLE
11676 rcStrict = g_apfnVMExitHandlers[VmxTransient.uExitReason](pVCpu, &VmxTransient);
11677#else
11678 rcStrict = hmR0VmxHandleExit(pVCpu, &VmxTransient);
11679#endif
11680 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11681 if (rcStrict == VINF_SUCCESS)
11682 {
11683 if (++(*pcLoops) <= cMaxResumeLoops)
11684 continue;
11685 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11686 rcStrict = VINF_EM_RAW_INTERRUPT;
11687 }
11688 break;
11689 }
11690
11691 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11692 return rcStrict;
11693}
11694
11695
11696#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
11697/**
11698 * Runs the nested-guest code using hardware-assisted VMX.
11699 *
11700 * @returns VBox status code.
11701 * @param pVCpu The cross context virtual CPU structure.
11702 * @param pcLoops Pointer to the number of executed loops.
11703 *
11704 * @sa hmR0VmxRunGuestCodeNormal.
11705 */
11706static VBOXSTRICTRC hmR0VmxRunGuestCodeNested(PVMCPU pVCpu, uint32_t *pcLoops)
11707{
11708 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
11709 Assert(pcLoops);
11710 Assert(*pcLoops <= cMaxResumeLoops);
11711 Assert(CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx));
11712
11713 /*
11714 * Switch to the nested-guest VMCS as we may have transitioned from executing the
11715 * guest without leaving ring-0. Otherwise, if we came from ring-3 we would have
11716 * loaded the nested-guest VMCS while entering the VMX ring-0 session.
11717 */
11718 if (!pVCpu->hm.s.vmx.fSwitchedToNstGstVmcs)
11719 {
11720 int rc = hmR0VmxSwitchToGstOrNstGstVmcs(pVCpu, true /* fSwitchToNstGstVmcs */);
11721 if (RT_SUCCESS(rc))
11722 { /* likely */ }
11723 else
11724 {
11725 LogRelFunc(("Failed to switch to the nested-guest VMCS. rc=%Rrc\n", rc));
11726 return rc;
11727 }
11728 }
11729
11730 VMXTRANSIENT VmxTransient;
11731 RT_ZERO(VmxTransient);
11732 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
11733 VmxTransient.fIsNestedGuest = true;
11734
11735 /* Paranoia. */
11736 Assert(VmxTransient.pVmcsInfo == &pVCpu->hm.s.vmx.VmcsInfoNstGst);
11737
11738 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
11739 for (;;)
11740 {
11741 Assert(!HMR0SuspendPending());
11742 HMVMX_ASSERT_CPU_SAFE(pVCpu);
11743 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
11744
11745 /*
11746 * Preparatory work for running guest code, this may force us to
11747 * return to ring-3.
11748 *
11749 * Warning! This bugger disables interrupts on VINF_SUCCESS!
11750 */
11751 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, false /* fStepping */);
11752 if (rcStrict != VINF_SUCCESS)
11753 break;
11754
11755 /* Interrupts are disabled at this point! */
11756 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
11757 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
11758 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
11759 /* Interrupts are re-enabled at this point! */
11760
11761 /*
11762 * Check for errors with running the VM (VMLAUNCH/VMRESUME).
11763 */
11764 if (RT_SUCCESS(rcRun))
11765 { /* very likely */ }
11766 else
11767 {
11768 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
11769 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
11770 return rcRun;
11771 }
11772
11773 /*
11774 * Profile the VM-exit.
11775 */
11776 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
11777 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
11778 STAM_COUNTER_INC(&pVCpu->hm.s.StatNestedExitAll);
11779 STAM_COUNTER_INC(&pVCpu->hm.s.paStatNestedExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
11780 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
11781 HMVMX_START_EXIT_DISPATCH_PROF();
11782
11783 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
11784
11785 /*
11786 * Handle the VM-exit.
11787 */
11788 rcStrict = hmR0VmxHandleExitNested(pVCpu, &VmxTransient);
11789 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
11790 if (rcStrict == VINF_SUCCESS)
11791 {
11792 if (!CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
11793 {
11794 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchNstGstVmexit);
11795 rcStrict = VINF_VMX_VMEXIT;
11796 }
11797 else
11798 {
11799 if (++(*pcLoops) <= cMaxResumeLoops)
11800 continue;
11801 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
11802 rcStrict = VINF_EM_RAW_INTERRUPT;
11803 }
11804 }
11805 else
11806 Assert(rcStrict != VINF_VMX_VMEXIT);
11807 break;
11808 }
11809
11810 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
11811 return rcStrict;
11812}
11813#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
11814
11815
11816/** @name Execution loop for single stepping, DBGF events and expensive Dtrace
11817 * probes.
11818 *
11819 * The following few functions and associated structure contains the bloat
11820 * necessary for providing detailed debug events and dtrace probes as well as
11821 * reliable host side single stepping. This works on the principle of
11822 * "subclassing" the normal execution loop and workers. We replace the loop
11823 * method completely and override selected helpers to add necessary adjustments
11824 * to their core operation.
11825 *
11826 * The goal is to keep the "parent" code lean and mean, so as not to sacrifice
11827 * any performance for debug and analysis features.
11828 *
11829 * @{
11830 */
11831
11832/**
11833 * Transient per-VCPU debug state of VMCS and related info. we save/restore in
11834 * the debug run loop.
11835 */
11836typedef struct VMXRUNDBGSTATE
11837{
11838 /** The RIP we started executing at. This is for detecting that we stepped. */
11839 uint64_t uRipStart;
11840 /** The CS we started executing with. */
11841 uint16_t uCsStart;
11842
11843 /** Whether we've actually modified the 1st execution control field. */
11844 bool fModifiedProcCtls : 1;
11845 /** Whether we've actually modified the 2nd execution control field. */
11846 bool fModifiedProcCtls2 : 1;
11847 /** Whether we've actually modified the exception bitmap. */
11848 bool fModifiedXcptBitmap : 1;
11849
11850 /** We desire the modified the CR0 mask to be cleared. */
11851 bool fClearCr0Mask : 1;
11852 /** We desire the modified the CR4 mask to be cleared. */
11853 bool fClearCr4Mask : 1;
11854 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC. */
11855 uint32_t fCpe1Extra;
11856 /** Stuff we do not want in VMX_VMCS32_CTRL_PROC_EXEC. */
11857 uint32_t fCpe1Unwanted;
11858 /** Stuff we need in VMX_VMCS32_CTRL_PROC_EXEC2. */
11859 uint32_t fCpe2Extra;
11860 /** Extra stuff we need in VMX_VMCS32_CTRL_EXCEPTION_BITMAP. */
11861 uint32_t bmXcptExtra;
11862 /** The sequence number of the Dtrace provider settings the state was
11863 * configured against. */
11864 uint32_t uDtraceSettingsSeqNo;
11865 /** VM-exits to check (one bit per VM-exit). */
11866 uint32_t bmExitsToCheck[3];
11867
11868 /** The initial VMX_VMCS32_CTRL_PROC_EXEC value (helps with restore). */
11869 uint32_t fProcCtlsInitial;
11870 /** The initial VMX_VMCS32_CTRL_PROC_EXEC2 value (helps with restore). */
11871 uint32_t fProcCtls2Initial;
11872 /** The initial VMX_VMCS32_CTRL_EXCEPTION_BITMAP value (helps with restore). */
11873 uint32_t bmXcptInitial;
11874} VMXRUNDBGSTATE;
11875AssertCompileMemberSize(VMXRUNDBGSTATE, bmExitsToCheck, (VMX_EXIT_MAX + 1 + 31) / 32 * 4);
11876typedef VMXRUNDBGSTATE *PVMXRUNDBGSTATE;
11877
11878
11879/**
11880 * Initializes the VMXRUNDBGSTATE structure.
11881 *
11882 * @param pVCpu The cross context virtual CPU structure of the
11883 * calling EMT.
11884 * @param pVmxTransient The VMX-transient structure.
11885 * @param pDbgState The debug state to initialize.
11886 */
11887static void hmR0VmxRunDebugStateInit(PVMCPU pVCpu, PCVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11888{
11889 pDbgState->uRipStart = pVCpu->cpum.GstCtx.rip;
11890 pDbgState->uCsStart = pVCpu->cpum.GstCtx.cs.Sel;
11891
11892 pDbgState->fModifiedProcCtls = false;
11893 pDbgState->fModifiedProcCtls2 = false;
11894 pDbgState->fModifiedXcptBitmap = false;
11895 pDbgState->fClearCr0Mask = false;
11896 pDbgState->fClearCr4Mask = false;
11897 pDbgState->fCpe1Extra = 0;
11898 pDbgState->fCpe1Unwanted = 0;
11899 pDbgState->fCpe2Extra = 0;
11900 pDbgState->bmXcptExtra = 0;
11901 pDbgState->fProcCtlsInitial = pVmxTransient->pVmcsInfo->u32ProcCtls;
11902 pDbgState->fProcCtls2Initial = pVmxTransient->pVmcsInfo->u32ProcCtls2;
11903 pDbgState->bmXcptInitial = pVmxTransient->pVmcsInfo->u32XcptBitmap;
11904}
11905
11906
11907/**
11908 * Updates the VMSC fields with changes requested by @a pDbgState.
11909 *
11910 * This is performed after hmR0VmxPreRunGuestDebugStateUpdate as well
11911 * immediately before executing guest code, i.e. when interrupts are disabled.
11912 * We don't check status codes here as we cannot easily assert or return in the
11913 * latter case.
11914 *
11915 * @param pVCpu The cross context virtual CPU structure.
11916 * @param pVmxTransient The VMX-transient structure.
11917 * @param pDbgState The debug state.
11918 */
11919static void hmR0VmxPreRunGuestDebugStateApply(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
11920{
11921 /*
11922 * Ensure desired flags in VMCS control fields are set.
11923 * (Ignoring write failure here, as we're committed and it's just debug extras.)
11924 *
11925 * Note! We load the shadow CR0 & CR4 bits when we flag the clearing, so
11926 * there should be no stale data in pCtx at this point.
11927 */
11928 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11929 if ( (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Extra) != pDbgState->fCpe1Extra
11930 || (pVmcsInfo->u32ProcCtls & pDbgState->fCpe1Unwanted))
11931 {
11932 pVmcsInfo->u32ProcCtls |= pDbgState->fCpe1Extra;
11933 pVmcsInfo->u32ProcCtls &= ~pDbgState->fCpe1Unwanted;
11934 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
11935 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC: %#RX32\n", pVmcsInfo->u32ProcCtls));
11936 pDbgState->fModifiedProcCtls = true;
11937 }
11938
11939 if ((pVmcsInfo->u32ProcCtls2 & pDbgState->fCpe2Extra) != pDbgState->fCpe2Extra)
11940 {
11941 pVmcsInfo->u32ProcCtls2 |= pDbgState->fCpe2Extra;
11942 VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pVmcsInfo->u32ProcCtls2);
11943 Log6Func(("VMX_VMCS32_CTRL_PROC_EXEC2: %#RX32\n", pVmcsInfo->u32ProcCtls2));
11944 pDbgState->fModifiedProcCtls2 = true;
11945 }
11946
11947 if ((pVmcsInfo->u32XcptBitmap & pDbgState->bmXcptExtra) != pDbgState->bmXcptExtra)
11948 {
11949 pVmcsInfo->u32XcptBitmap |= pDbgState->bmXcptExtra;
11950 VMXWriteVmcs32(VMX_VMCS32_CTRL_EXCEPTION_BITMAP, pVmcsInfo->u32XcptBitmap);
11951 Log6Func(("VMX_VMCS32_CTRL_EXCEPTION_BITMAP: %#RX32\n", pVmcsInfo->u32XcptBitmap));
11952 pDbgState->fModifiedXcptBitmap = true;
11953 }
11954
11955 if (pDbgState->fClearCr0Mask && pVmcsInfo->u64Cr0Mask != 0)
11956 {
11957 pVmcsInfo->u64Cr0Mask = 0;
11958 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, 0);
11959 Log6Func(("VMX_VMCS_CTRL_CR0_MASK: 0\n"));
11960 }
11961
11962 if (pDbgState->fClearCr4Mask && pVmcsInfo->u64Cr4Mask != 0)
11963 {
11964 pVmcsInfo->u64Cr4Mask = 0;
11965 VMXWriteVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, 0);
11966 Log6Func(("VMX_VMCS_CTRL_CR4_MASK: 0\n"));
11967 }
11968
11969 NOREF(pVCpu);
11970}
11971
11972
11973/**
11974 * Restores VMCS fields that were changed by hmR0VmxPreRunGuestDebugStateApply for
11975 * re-entry next time around.
11976 *
11977 * @returns Strict VBox status code (i.e. informational status codes too).
11978 * @param pVCpu The cross context virtual CPU structure.
11979 * @param pVmxTransient The VMX-transient structure.
11980 * @param pDbgState The debug state.
11981 * @param rcStrict The return code from executing the guest using single
11982 * stepping.
11983 */
11984static VBOXSTRICTRC hmR0VmxRunDebugStateRevert(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState,
11985 VBOXSTRICTRC rcStrict)
11986{
11987 /*
11988 * Restore VM-exit control settings as we may not reenter this function the
11989 * next time around.
11990 */
11991 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
11992
11993 /* We reload the initial value, trigger what we can of recalculations the
11994 next time around. From the looks of things, that's all that's required atm. */
11995 if (pDbgState->fModifiedProcCtls)
11996 {
11997 if (!(pDbgState->fProcCtlsInitial & VMX_PROC_CTLS_MOV_DR_EXIT) && CPUMIsHyperDebugStateActive(pVCpu))
11998 pDbgState->fProcCtlsInitial |= VMX_PROC_CTLS_MOV_DR_EXIT; /* Avoid assertion in hmR0VmxLeave */
11999 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pDbgState->fProcCtlsInitial);
12000 AssertRCReturn(rc2, rc2);
12001 pVmcsInfo->u32ProcCtls = pDbgState->fProcCtlsInitial;
12002 }
12003
12004 /* We're currently the only ones messing with this one, so just restore the
12005 cached value and reload the field. */
12006 if ( pDbgState->fModifiedProcCtls2
12007 && pVmcsInfo->u32ProcCtls2 != pDbgState->fProcCtls2Initial)
12008 {
12009 int rc2 = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC2, pDbgState->fProcCtls2Initial);
12010 AssertRCReturn(rc2, rc2);
12011 pVmcsInfo->u32ProcCtls2 = pDbgState->fProcCtls2Initial;
12012 }
12013
12014 /* If we've modified the exception bitmap, we restore it and trigger
12015 reloading and partial recalculation the next time around. */
12016 if (pDbgState->fModifiedXcptBitmap)
12017 pVmcsInfo->u32XcptBitmap = pDbgState->bmXcptInitial;
12018
12019 return rcStrict;
12020}
12021
12022
12023/**
12024 * Configures VM-exit controls for current DBGF and DTrace settings.
12025 *
12026 * This updates @a pDbgState and the VMCS execution control fields to reflect
12027 * the necessary VM-exits demanded by DBGF and DTrace.
12028 *
12029 * @param pVCpu The cross context virtual CPU structure.
12030 * @param pVmxTransient The VMX-transient structure. May update
12031 * fUpdatedTscOffsettingAndPreemptTimer.
12032 * @param pDbgState The debug state.
12033 */
12034static void hmR0VmxPreRunGuestDebugStateUpdate(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12035{
12036 /*
12037 * Take down the dtrace serial number so we can spot changes.
12038 */
12039 pDbgState->uDtraceSettingsSeqNo = VBOXVMM_GET_SETTINGS_SEQ_NO();
12040 ASMCompilerBarrier();
12041
12042 /*
12043 * We'll rebuild most of the middle block of data members (holding the
12044 * current settings) as we go along here, so start by clearing it all.
12045 */
12046 pDbgState->bmXcptExtra = 0;
12047 pDbgState->fCpe1Extra = 0;
12048 pDbgState->fCpe1Unwanted = 0;
12049 pDbgState->fCpe2Extra = 0;
12050 for (unsigned i = 0; i < RT_ELEMENTS(pDbgState->bmExitsToCheck); i++)
12051 pDbgState->bmExitsToCheck[i] = 0;
12052
12053 /*
12054 * Software interrupts (INT XXh) - no idea how to trigger these...
12055 */
12056 PVM pVM = pVCpu->CTX_SUFF(pVM);
12057 if ( DBGF_IS_EVENT_ENABLED(pVM, DBGFEVENT_INTERRUPT_SOFTWARE)
12058 || VBOXVMM_INT_SOFTWARE_ENABLED())
12059 {
12060 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12061 }
12062
12063 /*
12064 * INT3 breakpoints - triggered by #BP exceptions.
12065 */
12066 if (pVM->dbgf.ro.cEnabledInt3Breakpoints > 0)
12067 pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12068
12069 /*
12070 * Exception bitmap and XCPT events+probes.
12071 */
12072 for (int iXcpt = 0; iXcpt < (DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST + 1); iXcpt++)
12073 if (DBGF_IS_EVENT_ENABLED(pVM, (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + iXcpt)))
12074 pDbgState->bmXcptExtra |= RT_BIT_32(iXcpt);
12075
12076 if (VBOXVMM_XCPT_DE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DE);
12077 if (VBOXVMM_XCPT_DB_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DB);
12078 if (VBOXVMM_XCPT_BP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BP);
12079 if (VBOXVMM_XCPT_OF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_OF);
12080 if (VBOXVMM_XCPT_BR_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_BR);
12081 if (VBOXVMM_XCPT_UD_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_UD);
12082 if (VBOXVMM_XCPT_NM_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NM);
12083 if (VBOXVMM_XCPT_DF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_DF);
12084 if (VBOXVMM_XCPT_TS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_TS);
12085 if (VBOXVMM_XCPT_NP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_NP);
12086 if (VBOXVMM_XCPT_SS_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SS);
12087 if (VBOXVMM_XCPT_GP_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_GP);
12088 if (VBOXVMM_XCPT_PF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_PF);
12089 if (VBOXVMM_XCPT_MF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_MF);
12090 if (VBOXVMM_XCPT_AC_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_AC);
12091 if (VBOXVMM_XCPT_XF_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_XF);
12092 if (VBOXVMM_XCPT_VE_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_VE);
12093 if (VBOXVMM_XCPT_SX_ENABLED()) pDbgState->bmXcptExtra |= RT_BIT_32(X86_XCPT_SX);
12094
12095 if (pDbgState->bmXcptExtra)
12096 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_XCPT_OR_NMI);
12097
12098 /*
12099 * Process events and probes for VM-exits, making sure we get the wanted VM-exits.
12100 *
12101 * Note! This is the reverse of what hmR0VmxHandleExitDtraceEvents does.
12102 * So, when adding/changing/removing please don't forget to update it.
12103 *
12104 * Some of the macros are picking up local variables to save horizontal space,
12105 * (being able to see it in a table is the lesser evil here).
12106 */
12107#define IS_EITHER_ENABLED(a_pVM, a_EventSubName) \
12108 ( DBGF_IS_EVENT_ENABLED(a_pVM, RT_CONCAT(DBGFEVENT_, a_EventSubName)) \
12109 || RT_CONCAT3(VBOXVMM_, a_EventSubName, _ENABLED)() )
12110#define SET_ONLY_XBM_IF_EITHER_EN(a_EventSubName, a_uExit) \
12111 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12112 { AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12113 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12114 } else do { } while (0)
12115#define SET_CPE1_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec) \
12116 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12117 { \
12118 (pDbgState)->fCpe1Extra |= (a_fCtrlProcExec); \
12119 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12120 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12121 } else do { } while (0)
12122#define SET_CPEU_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fUnwantedCtrlProcExec) \
12123 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12124 { \
12125 (pDbgState)->fCpe1Unwanted |= (a_fUnwantedCtrlProcExec); \
12126 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12127 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12128 } else do { } while (0)
12129#define SET_CPE2_XBM_IF_EITHER_EN(a_EventSubName, a_uExit, a_fCtrlProcExec2) \
12130 if (IS_EITHER_ENABLED(pVM, a_EventSubName)) \
12131 { \
12132 (pDbgState)->fCpe2Extra |= (a_fCtrlProcExec2); \
12133 AssertCompile((unsigned)(a_uExit) < sizeof(pDbgState->bmExitsToCheck) * 8); \
12134 ASMBitSet((pDbgState)->bmExitsToCheck, a_uExit); \
12135 } else do { } while (0)
12136
12137 SET_ONLY_XBM_IF_EITHER_EN(EXIT_TASK_SWITCH, VMX_EXIT_TASK_SWITCH); /* unconditional */
12138 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_VIOLATION, VMX_EXIT_EPT_VIOLATION); /* unconditional */
12139 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_EPT_MISCONFIG, VMX_EXIT_EPT_MISCONFIG); /* unconditional (unless #VE) */
12140 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_ACCESS, VMX_EXIT_APIC_ACCESS); /* feature dependent, nothing to enable here */
12141 SET_ONLY_XBM_IF_EITHER_EN(EXIT_VMX_VAPIC_WRITE, VMX_EXIT_APIC_WRITE); /* feature dependent, nothing to enable here */
12142
12143 SET_ONLY_XBM_IF_EITHER_EN(INSTR_CPUID, VMX_EXIT_CPUID); /* unconditional */
12144 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CPUID, VMX_EXIT_CPUID);
12145 SET_ONLY_XBM_IF_EITHER_EN(INSTR_GETSEC, VMX_EXIT_GETSEC); /* unconditional */
12146 SET_ONLY_XBM_IF_EITHER_EN( EXIT_GETSEC, VMX_EXIT_GETSEC);
12147 SET_CPE1_XBM_IF_EITHER_EN(INSTR_HALT, VMX_EXIT_HLT, VMX_PROC_CTLS_HLT_EXIT); /* paranoia */
12148 SET_ONLY_XBM_IF_EITHER_EN( EXIT_HALT, VMX_EXIT_HLT);
12149 SET_ONLY_XBM_IF_EITHER_EN(INSTR_INVD, VMX_EXIT_INVD); /* unconditional */
12150 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVD, VMX_EXIT_INVD);
12151 SET_CPE1_XBM_IF_EITHER_EN(INSTR_INVLPG, VMX_EXIT_INVLPG, VMX_PROC_CTLS_INVLPG_EXIT);
12152 SET_ONLY_XBM_IF_EITHER_EN( EXIT_INVLPG, VMX_EXIT_INVLPG);
12153 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDPMC, VMX_EXIT_RDPMC, VMX_PROC_CTLS_RDPMC_EXIT);
12154 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDPMC, VMX_EXIT_RDPMC);
12155 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSC, VMX_EXIT_RDTSC, VMX_PROC_CTLS_RDTSC_EXIT);
12156 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSC, VMX_EXIT_RDTSC);
12157 SET_ONLY_XBM_IF_EITHER_EN(INSTR_RSM, VMX_EXIT_RSM); /* unconditional */
12158 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RSM, VMX_EXIT_RSM);
12159 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMM_CALL, VMX_EXIT_VMCALL); /* unconditional */
12160 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMM_CALL, VMX_EXIT_VMCALL);
12161 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMCLEAR, VMX_EXIT_VMCLEAR); /* unconditional */
12162 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMCLEAR, VMX_EXIT_VMCLEAR);
12163 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH); /* unconditional */
12164 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMLAUNCH, VMX_EXIT_VMLAUNCH);
12165 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRLD, VMX_EXIT_VMPTRLD); /* unconditional */
12166 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRLD, VMX_EXIT_VMPTRLD);
12167 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMPTRST, VMX_EXIT_VMPTRST); /* unconditional */
12168 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMPTRST, VMX_EXIT_VMPTRST);
12169 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMREAD, VMX_EXIT_VMREAD); /* unconditional */
12170 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMREAD, VMX_EXIT_VMREAD);
12171 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMRESUME, VMX_EXIT_VMRESUME); /* unconditional */
12172 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMRESUME, VMX_EXIT_VMRESUME);
12173 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMWRITE, VMX_EXIT_VMWRITE); /* unconditional */
12174 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMWRITE, VMX_EXIT_VMWRITE);
12175 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXOFF, VMX_EXIT_VMXOFF); /* unconditional */
12176 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXOFF, VMX_EXIT_VMXOFF);
12177 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMXON, VMX_EXIT_VMXON); /* unconditional */
12178 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMXON, VMX_EXIT_VMXON);
12179
12180 if ( IS_EITHER_ENABLED(pVM, INSTR_CRX_READ)
12181 || IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12182 {
12183 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR4
12184 | CPUMCTX_EXTRN_APIC_TPR);
12185 AssertRC(rc);
12186
12187#if 0 /** @todo fix me */
12188 pDbgState->fClearCr0Mask = true;
12189 pDbgState->fClearCr4Mask = true;
12190#endif
12191 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_READ))
12192 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_STORE_EXIT | VMX_PROC_CTLS_CR8_STORE_EXIT;
12193 if (IS_EITHER_ENABLED(pVM, INSTR_CRX_WRITE))
12194 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_CR3_LOAD_EXIT | VMX_PROC_CTLS_CR8_LOAD_EXIT;
12195 pDbgState->fCpe1Unwanted |= VMX_PROC_CTLS_USE_TPR_SHADOW; /* risky? */
12196 /* Note! We currently don't use VMX_VMCS32_CTRL_CR3_TARGET_COUNT. It would
12197 require clearing here and in the loop if we start using it. */
12198 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_CRX);
12199 }
12200 else
12201 {
12202 if (pDbgState->fClearCr0Mask)
12203 {
12204 pDbgState->fClearCr0Mask = false;
12205 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR0);
12206 }
12207 if (pDbgState->fClearCr4Mask)
12208 {
12209 pDbgState->fClearCr4Mask = false;
12210 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_CR4);
12211 }
12212 }
12213 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_READ, VMX_EXIT_MOV_CRX);
12214 SET_ONLY_XBM_IF_EITHER_EN( EXIT_CRX_WRITE, VMX_EXIT_MOV_CRX);
12215
12216 if ( IS_EITHER_ENABLED(pVM, INSTR_DRX_READ)
12217 || IS_EITHER_ENABLED(pVM, INSTR_DRX_WRITE))
12218 {
12219 /** @todo later, need to fix handler as it assumes this won't usually happen. */
12220 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_MOV_DRX);
12221 }
12222 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_READ, VMX_EXIT_MOV_DRX);
12223 SET_ONLY_XBM_IF_EITHER_EN( EXIT_DRX_WRITE, VMX_EXIT_MOV_DRX);
12224
12225 SET_CPEU_XBM_IF_EITHER_EN(INSTR_RDMSR, VMX_EXIT_RDMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS); /* risky clearing this? */
12226 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDMSR, VMX_EXIT_RDMSR);
12227 SET_CPEU_XBM_IF_EITHER_EN(INSTR_WRMSR, VMX_EXIT_WRMSR, VMX_PROC_CTLS_USE_MSR_BITMAPS);
12228 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WRMSR, VMX_EXIT_WRMSR);
12229 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MWAIT, VMX_EXIT_MWAIT, VMX_PROC_CTLS_MWAIT_EXIT); /* paranoia */
12230 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MWAIT, VMX_EXIT_MWAIT);
12231 SET_CPE1_XBM_IF_EITHER_EN(INSTR_MONITOR, VMX_EXIT_MONITOR, VMX_PROC_CTLS_MONITOR_EXIT); /* paranoia */
12232 SET_ONLY_XBM_IF_EITHER_EN( EXIT_MONITOR, VMX_EXIT_MONITOR);
12233#if 0 /** @todo too slow, fix handler. */
12234 SET_CPE1_XBM_IF_EITHER_EN(INSTR_PAUSE, VMX_EXIT_PAUSE, VMX_PROC_CTLS_PAUSE_EXIT);
12235#endif
12236 SET_ONLY_XBM_IF_EITHER_EN( EXIT_PAUSE, VMX_EXIT_PAUSE);
12237
12238 if ( IS_EITHER_ENABLED(pVM, INSTR_SGDT)
12239 || IS_EITHER_ENABLED(pVM, INSTR_SIDT)
12240 || IS_EITHER_ENABLED(pVM, INSTR_LGDT)
12241 || IS_EITHER_ENABLED(pVM, INSTR_LIDT))
12242 {
12243 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12244 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_GDTR_IDTR_ACCESS);
12245 }
12246 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12247 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12248 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LGDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12249 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LIDT, VMX_EXIT_GDTR_IDTR_ACCESS);
12250
12251 if ( IS_EITHER_ENABLED(pVM, INSTR_SLDT)
12252 || IS_EITHER_ENABLED(pVM, INSTR_STR)
12253 || IS_EITHER_ENABLED(pVM, INSTR_LLDT)
12254 || IS_EITHER_ENABLED(pVM, INSTR_LTR))
12255 {
12256 pDbgState->fCpe2Extra |= VMX_PROC_CTLS2_DESC_TABLE_EXIT;
12257 ASMBitSet(pDbgState->bmExitsToCheck, VMX_EXIT_LDTR_TR_ACCESS);
12258 }
12259 SET_ONLY_XBM_IF_EITHER_EN( EXIT_SLDT, VMX_EXIT_LDTR_TR_ACCESS);
12260 SET_ONLY_XBM_IF_EITHER_EN( EXIT_STR, VMX_EXIT_LDTR_TR_ACCESS);
12261 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LLDT, VMX_EXIT_LDTR_TR_ACCESS);
12262 SET_ONLY_XBM_IF_EITHER_EN( EXIT_LTR, VMX_EXIT_LDTR_TR_ACCESS);
12263
12264 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVEPT, VMX_EXIT_INVEPT); /* unconditional */
12265 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVEPT, VMX_EXIT_INVEPT);
12266 SET_CPE1_XBM_IF_EITHER_EN(INSTR_RDTSCP, VMX_EXIT_RDTSCP, VMX_PROC_CTLS_RDTSC_EXIT);
12267 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDTSCP, VMX_EXIT_RDTSCP);
12268 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_INVVPID, VMX_EXIT_INVVPID); /* unconditional */
12269 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVVPID, VMX_EXIT_INVVPID);
12270 SET_CPE2_XBM_IF_EITHER_EN(INSTR_WBINVD, VMX_EXIT_WBINVD, VMX_PROC_CTLS2_WBINVD_EXIT);
12271 SET_ONLY_XBM_IF_EITHER_EN( EXIT_WBINVD, VMX_EXIT_WBINVD);
12272 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSETBV, VMX_EXIT_XSETBV); /* unconditional */
12273 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XSETBV, VMX_EXIT_XSETBV);
12274 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDRAND, VMX_EXIT_RDRAND, VMX_PROC_CTLS2_RDRAND_EXIT);
12275 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDRAND, VMX_EXIT_RDRAND);
12276 SET_CPE1_XBM_IF_EITHER_EN(INSTR_VMX_INVPCID, VMX_EXIT_INVPCID, VMX_PROC_CTLS_INVLPG_EXIT);
12277 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_INVPCID, VMX_EXIT_INVPCID);
12278 SET_ONLY_XBM_IF_EITHER_EN(INSTR_VMX_VMFUNC, VMX_EXIT_VMFUNC); /* unconditional for the current setup */
12279 SET_ONLY_XBM_IF_EITHER_EN( EXIT_VMX_VMFUNC, VMX_EXIT_VMFUNC);
12280 SET_CPE2_XBM_IF_EITHER_EN(INSTR_RDSEED, VMX_EXIT_RDSEED, VMX_PROC_CTLS2_RDSEED_EXIT);
12281 SET_ONLY_XBM_IF_EITHER_EN( EXIT_RDSEED, VMX_EXIT_RDSEED);
12282 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XSAVES, VMX_EXIT_XSAVES); /* unconditional (enabled by host, guest cfg) */
12283 SET_ONLY_XBM_IF_EITHER_EN(EXIT_XSAVES, VMX_EXIT_XSAVES);
12284 SET_ONLY_XBM_IF_EITHER_EN(INSTR_XRSTORS, VMX_EXIT_XRSTORS); /* unconditional (enabled by host, guest cfg) */
12285 SET_ONLY_XBM_IF_EITHER_EN( EXIT_XRSTORS, VMX_EXIT_XRSTORS);
12286
12287#undef IS_EITHER_ENABLED
12288#undef SET_ONLY_XBM_IF_EITHER_EN
12289#undef SET_CPE1_XBM_IF_EITHER_EN
12290#undef SET_CPEU_XBM_IF_EITHER_EN
12291#undef SET_CPE2_XBM_IF_EITHER_EN
12292
12293 /*
12294 * Sanitize the control stuff.
12295 */
12296 pDbgState->fCpe2Extra &= pVM->hm.s.vmx.Msrs.ProcCtls2.n.allowed1;
12297 if (pDbgState->fCpe2Extra)
12298 pDbgState->fCpe1Extra |= VMX_PROC_CTLS_USE_SECONDARY_CTLS;
12299 pDbgState->fCpe1Extra &= pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed1;
12300 pDbgState->fCpe1Unwanted &= ~pVM->hm.s.vmx.Msrs.ProcCtls.n.allowed0;
12301 if (pVCpu->hm.s.fDebugWantRdTscExit != RT_BOOL(pDbgState->fCpe1Extra & VMX_PROC_CTLS_RDTSC_EXIT))
12302 {
12303 pVCpu->hm.s.fDebugWantRdTscExit ^= true;
12304 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
12305 }
12306
12307 Log6(("HM: debug state: cpe1=%#RX32 cpeu=%#RX32 cpe2=%#RX32%s%s\n",
12308 pDbgState->fCpe1Extra, pDbgState->fCpe1Unwanted, pDbgState->fCpe2Extra,
12309 pDbgState->fClearCr0Mask ? " clr-cr0" : "",
12310 pDbgState->fClearCr4Mask ? " clr-cr4" : ""));
12311}
12312
12313
12314/**
12315 * Fires off DBGF events and dtrace probes for a VM-exit, when it's
12316 * appropriate.
12317 *
12318 * The caller has checked the VM-exit against the
12319 * VMXRUNDBGSTATE::bmExitsToCheck bitmap. The caller has checked for NMIs
12320 * already, so we don't have to do that either.
12321 *
12322 * @returns Strict VBox status code (i.e. informational status codes too).
12323 * @param pVCpu The cross context virtual CPU structure.
12324 * @param pVmxTransient The VMX-transient structure.
12325 * @param uExitReason The VM-exit reason.
12326 *
12327 * @remarks The name of this function is displayed by dtrace, so keep it short
12328 * and to the point. No longer than 33 chars long, please.
12329 */
12330static VBOXSTRICTRC hmR0VmxHandleExitDtraceEvents(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint32_t uExitReason)
12331{
12332 /*
12333 * Translate the event into a DBGF event (enmEvent + uEventArg) and at the
12334 * same time check whether any corresponding Dtrace event is enabled (fDtrace).
12335 *
12336 * Note! This is the reverse operation of what hmR0VmxPreRunGuestDebugStateUpdate
12337 * does. Must add/change/remove both places. Same ordering, please.
12338 *
12339 * Added/removed events must also be reflected in the next section
12340 * where we dispatch dtrace events.
12341 */
12342 bool fDtrace1 = false;
12343 bool fDtrace2 = false;
12344 DBGFEVENTTYPE enmEvent1 = DBGFEVENT_END;
12345 DBGFEVENTTYPE enmEvent2 = DBGFEVENT_END;
12346 uint32_t uEventArg = 0;
12347#define SET_EXIT(a_EventSubName) \
12348 do { \
12349 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12350 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12351 } while (0)
12352#define SET_BOTH(a_EventSubName) \
12353 do { \
12354 enmEvent1 = RT_CONCAT(DBGFEVENT_INSTR_, a_EventSubName); \
12355 enmEvent2 = RT_CONCAT(DBGFEVENT_EXIT_, a_EventSubName); \
12356 fDtrace1 = RT_CONCAT3(VBOXVMM_INSTR_, a_EventSubName, _ENABLED)(); \
12357 fDtrace2 = RT_CONCAT3(VBOXVMM_EXIT_, a_EventSubName, _ENABLED)(); \
12358 } while (0)
12359 switch (uExitReason)
12360 {
12361 case VMX_EXIT_MTF:
12362 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12363
12364 case VMX_EXIT_XCPT_OR_NMI:
12365 {
12366 uint8_t const idxVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
12367 switch (VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo))
12368 {
12369 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
12370 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
12371 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
12372 if (idxVector <= (unsigned)(DBGFEVENT_XCPT_LAST - DBGFEVENT_XCPT_FIRST))
12373 {
12374 if (VMX_EXIT_INT_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uExitIntInfo))
12375 {
12376 hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
12377 uEventArg = pVmxTransient->uExitIntErrorCode;
12378 }
12379 enmEvent1 = (DBGFEVENTTYPE)(DBGFEVENT_XCPT_FIRST + idxVector);
12380 switch (enmEvent1)
12381 {
12382 case DBGFEVENT_XCPT_DE: fDtrace1 = VBOXVMM_XCPT_DE_ENABLED(); break;
12383 case DBGFEVENT_XCPT_DB: fDtrace1 = VBOXVMM_XCPT_DB_ENABLED(); break;
12384 case DBGFEVENT_XCPT_BP: fDtrace1 = VBOXVMM_XCPT_BP_ENABLED(); break;
12385 case DBGFEVENT_XCPT_OF: fDtrace1 = VBOXVMM_XCPT_OF_ENABLED(); break;
12386 case DBGFEVENT_XCPT_BR: fDtrace1 = VBOXVMM_XCPT_BR_ENABLED(); break;
12387 case DBGFEVENT_XCPT_UD: fDtrace1 = VBOXVMM_XCPT_UD_ENABLED(); break;
12388 case DBGFEVENT_XCPT_NM: fDtrace1 = VBOXVMM_XCPT_NM_ENABLED(); break;
12389 case DBGFEVENT_XCPT_DF: fDtrace1 = VBOXVMM_XCPT_DF_ENABLED(); break;
12390 case DBGFEVENT_XCPT_TS: fDtrace1 = VBOXVMM_XCPT_TS_ENABLED(); break;
12391 case DBGFEVENT_XCPT_NP: fDtrace1 = VBOXVMM_XCPT_NP_ENABLED(); break;
12392 case DBGFEVENT_XCPT_SS: fDtrace1 = VBOXVMM_XCPT_SS_ENABLED(); break;
12393 case DBGFEVENT_XCPT_GP: fDtrace1 = VBOXVMM_XCPT_GP_ENABLED(); break;
12394 case DBGFEVENT_XCPT_PF: fDtrace1 = VBOXVMM_XCPT_PF_ENABLED(); break;
12395 case DBGFEVENT_XCPT_MF: fDtrace1 = VBOXVMM_XCPT_MF_ENABLED(); break;
12396 case DBGFEVENT_XCPT_AC: fDtrace1 = VBOXVMM_XCPT_AC_ENABLED(); break;
12397 case DBGFEVENT_XCPT_XF: fDtrace1 = VBOXVMM_XCPT_XF_ENABLED(); break;
12398 case DBGFEVENT_XCPT_VE: fDtrace1 = VBOXVMM_XCPT_VE_ENABLED(); break;
12399 case DBGFEVENT_XCPT_SX: fDtrace1 = VBOXVMM_XCPT_SX_ENABLED(); break;
12400 default: break;
12401 }
12402 }
12403 else
12404 AssertFailed();
12405 break;
12406
12407 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
12408 uEventArg = idxVector;
12409 enmEvent1 = DBGFEVENT_INTERRUPT_SOFTWARE;
12410 fDtrace1 = VBOXVMM_INT_SOFTWARE_ENABLED();
12411 break;
12412 }
12413 break;
12414 }
12415
12416 case VMX_EXIT_TRIPLE_FAULT:
12417 enmEvent1 = DBGFEVENT_TRIPLE_FAULT;
12418 //fDtrace1 = VBOXVMM_EXIT_TRIPLE_FAULT_ENABLED();
12419 break;
12420 case VMX_EXIT_TASK_SWITCH: SET_EXIT(TASK_SWITCH); break;
12421 case VMX_EXIT_EPT_VIOLATION: SET_EXIT(VMX_EPT_VIOLATION); break;
12422 case VMX_EXIT_EPT_MISCONFIG: SET_EXIT(VMX_EPT_MISCONFIG); break;
12423 case VMX_EXIT_APIC_ACCESS: SET_EXIT(VMX_VAPIC_ACCESS); break;
12424 case VMX_EXIT_APIC_WRITE: SET_EXIT(VMX_VAPIC_WRITE); break;
12425
12426 /* Instruction specific VM-exits: */
12427 case VMX_EXIT_CPUID: SET_BOTH(CPUID); break;
12428 case VMX_EXIT_GETSEC: SET_BOTH(GETSEC); break;
12429 case VMX_EXIT_HLT: SET_BOTH(HALT); break;
12430 case VMX_EXIT_INVD: SET_BOTH(INVD); break;
12431 case VMX_EXIT_INVLPG: SET_BOTH(INVLPG); break;
12432 case VMX_EXIT_RDPMC: SET_BOTH(RDPMC); break;
12433 case VMX_EXIT_RDTSC: SET_BOTH(RDTSC); break;
12434 case VMX_EXIT_RSM: SET_BOTH(RSM); break;
12435 case VMX_EXIT_VMCALL: SET_BOTH(VMM_CALL); break;
12436 case VMX_EXIT_VMCLEAR: SET_BOTH(VMX_VMCLEAR); break;
12437 case VMX_EXIT_VMLAUNCH: SET_BOTH(VMX_VMLAUNCH); break;
12438 case VMX_EXIT_VMPTRLD: SET_BOTH(VMX_VMPTRLD); break;
12439 case VMX_EXIT_VMPTRST: SET_BOTH(VMX_VMPTRST); break;
12440 case VMX_EXIT_VMREAD: SET_BOTH(VMX_VMREAD); break;
12441 case VMX_EXIT_VMRESUME: SET_BOTH(VMX_VMRESUME); break;
12442 case VMX_EXIT_VMWRITE: SET_BOTH(VMX_VMWRITE); break;
12443 case VMX_EXIT_VMXOFF: SET_BOTH(VMX_VMXOFF); break;
12444 case VMX_EXIT_VMXON: SET_BOTH(VMX_VMXON); break;
12445 case VMX_EXIT_MOV_CRX:
12446 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12447 if (VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_CRX_ACCESS_READ)
12448 SET_BOTH(CRX_READ);
12449 else
12450 SET_BOTH(CRX_WRITE);
12451 uEventArg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
12452 break;
12453 case VMX_EXIT_MOV_DRX:
12454 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12455 if ( VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual)
12456 == VMX_EXIT_QUAL_DRX_DIRECTION_READ)
12457 SET_BOTH(DRX_READ);
12458 else
12459 SET_BOTH(DRX_WRITE);
12460 uEventArg = VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual);
12461 break;
12462 case VMX_EXIT_RDMSR: SET_BOTH(RDMSR); break;
12463 case VMX_EXIT_WRMSR: SET_BOTH(WRMSR); break;
12464 case VMX_EXIT_MWAIT: SET_BOTH(MWAIT); break;
12465 case VMX_EXIT_MONITOR: SET_BOTH(MONITOR); break;
12466 case VMX_EXIT_PAUSE: SET_BOTH(PAUSE); break;
12467 case VMX_EXIT_GDTR_IDTR_ACCESS:
12468 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12469 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_XDTR_INSINFO_INSTR_ID))
12470 {
12471 case VMX_XDTR_INSINFO_II_SGDT: SET_BOTH(SGDT); break;
12472 case VMX_XDTR_INSINFO_II_SIDT: SET_BOTH(SIDT); break;
12473 case VMX_XDTR_INSINFO_II_LGDT: SET_BOTH(LGDT); break;
12474 case VMX_XDTR_INSINFO_II_LIDT: SET_BOTH(LIDT); break;
12475 }
12476 break;
12477
12478 case VMX_EXIT_LDTR_TR_ACCESS:
12479 hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
12480 switch (RT_BF_GET(pVmxTransient->ExitInstrInfo.u, VMX_BF_YYTR_INSINFO_INSTR_ID))
12481 {
12482 case VMX_YYTR_INSINFO_II_SLDT: SET_BOTH(SLDT); break;
12483 case VMX_YYTR_INSINFO_II_STR: SET_BOTH(STR); break;
12484 case VMX_YYTR_INSINFO_II_LLDT: SET_BOTH(LLDT); break;
12485 case VMX_YYTR_INSINFO_II_LTR: SET_BOTH(LTR); break;
12486 }
12487 break;
12488
12489 case VMX_EXIT_INVEPT: SET_BOTH(VMX_INVEPT); break;
12490 case VMX_EXIT_RDTSCP: SET_BOTH(RDTSCP); break;
12491 case VMX_EXIT_INVVPID: SET_BOTH(VMX_INVVPID); break;
12492 case VMX_EXIT_WBINVD: SET_BOTH(WBINVD); break;
12493 case VMX_EXIT_XSETBV: SET_BOTH(XSETBV); break;
12494 case VMX_EXIT_RDRAND: SET_BOTH(RDRAND); break;
12495 case VMX_EXIT_INVPCID: SET_BOTH(VMX_INVPCID); break;
12496 case VMX_EXIT_VMFUNC: SET_BOTH(VMX_VMFUNC); break;
12497 case VMX_EXIT_RDSEED: SET_BOTH(RDSEED); break;
12498 case VMX_EXIT_XSAVES: SET_BOTH(XSAVES); break;
12499 case VMX_EXIT_XRSTORS: SET_BOTH(XRSTORS); break;
12500
12501 /* Events that aren't relevant at this point. */
12502 case VMX_EXIT_EXT_INT:
12503 case VMX_EXIT_INT_WINDOW:
12504 case VMX_EXIT_NMI_WINDOW:
12505 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12506 case VMX_EXIT_PREEMPT_TIMER:
12507 case VMX_EXIT_IO_INSTR:
12508 break;
12509
12510 /* Errors and unexpected events. */
12511 case VMX_EXIT_INIT_SIGNAL:
12512 case VMX_EXIT_SIPI:
12513 case VMX_EXIT_IO_SMI:
12514 case VMX_EXIT_SMI:
12515 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12516 case VMX_EXIT_ERR_MSR_LOAD:
12517 case VMX_EXIT_ERR_MACHINE_CHECK:
12518 case VMX_EXIT_PML_FULL:
12519 case VMX_EXIT_VIRTUALIZED_EOI:
12520 break;
12521
12522 default:
12523 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12524 break;
12525 }
12526#undef SET_BOTH
12527#undef SET_EXIT
12528
12529 /*
12530 * Dtrace tracepoints go first. We do them here at once so we don't
12531 * have to copy the guest state saving and stuff a few dozen times.
12532 * Down side is that we've got to repeat the switch, though this time
12533 * we use enmEvent since the probes are a subset of what DBGF does.
12534 */
12535 if (fDtrace1 || fDtrace2)
12536 {
12537 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12538 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12539 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
12540 switch (enmEvent1)
12541 {
12542 /** @todo consider which extra parameters would be helpful for each probe. */
12543 case DBGFEVENT_END: break;
12544 case DBGFEVENT_XCPT_DE: VBOXVMM_XCPT_DE(pVCpu, pCtx); break;
12545 case DBGFEVENT_XCPT_DB: VBOXVMM_XCPT_DB(pVCpu, pCtx, pCtx->dr[6]); break;
12546 case DBGFEVENT_XCPT_BP: VBOXVMM_XCPT_BP(pVCpu, pCtx); break;
12547 case DBGFEVENT_XCPT_OF: VBOXVMM_XCPT_OF(pVCpu, pCtx); break;
12548 case DBGFEVENT_XCPT_BR: VBOXVMM_XCPT_BR(pVCpu, pCtx); break;
12549 case DBGFEVENT_XCPT_UD: VBOXVMM_XCPT_UD(pVCpu, pCtx); break;
12550 case DBGFEVENT_XCPT_NM: VBOXVMM_XCPT_NM(pVCpu, pCtx); break;
12551 case DBGFEVENT_XCPT_DF: VBOXVMM_XCPT_DF(pVCpu, pCtx); break;
12552 case DBGFEVENT_XCPT_TS: VBOXVMM_XCPT_TS(pVCpu, pCtx, uEventArg); break;
12553 case DBGFEVENT_XCPT_NP: VBOXVMM_XCPT_NP(pVCpu, pCtx, uEventArg); break;
12554 case DBGFEVENT_XCPT_SS: VBOXVMM_XCPT_SS(pVCpu, pCtx, uEventArg); break;
12555 case DBGFEVENT_XCPT_GP: VBOXVMM_XCPT_GP(pVCpu, pCtx, uEventArg); break;
12556 case DBGFEVENT_XCPT_PF: VBOXVMM_XCPT_PF(pVCpu, pCtx, uEventArg, pCtx->cr2); break;
12557 case DBGFEVENT_XCPT_MF: VBOXVMM_XCPT_MF(pVCpu, pCtx); break;
12558 case DBGFEVENT_XCPT_AC: VBOXVMM_XCPT_AC(pVCpu, pCtx); break;
12559 case DBGFEVENT_XCPT_XF: VBOXVMM_XCPT_XF(pVCpu, pCtx); break;
12560 case DBGFEVENT_XCPT_VE: VBOXVMM_XCPT_VE(pVCpu, pCtx); break;
12561 case DBGFEVENT_XCPT_SX: VBOXVMM_XCPT_SX(pVCpu, pCtx, uEventArg); break;
12562 case DBGFEVENT_INTERRUPT_SOFTWARE: VBOXVMM_INT_SOFTWARE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12563 case DBGFEVENT_INSTR_CPUID: VBOXVMM_INSTR_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12564 case DBGFEVENT_INSTR_GETSEC: VBOXVMM_INSTR_GETSEC(pVCpu, pCtx); break;
12565 case DBGFEVENT_INSTR_HALT: VBOXVMM_INSTR_HALT(pVCpu, pCtx); break;
12566 case DBGFEVENT_INSTR_INVD: VBOXVMM_INSTR_INVD(pVCpu, pCtx); break;
12567 case DBGFEVENT_INSTR_INVLPG: VBOXVMM_INSTR_INVLPG(pVCpu, pCtx); break;
12568 case DBGFEVENT_INSTR_RDPMC: VBOXVMM_INSTR_RDPMC(pVCpu, pCtx); break;
12569 case DBGFEVENT_INSTR_RDTSC: VBOXVMM_INSTR_RDTSC(pVCpu, pCtx); break;
12570 case DBGFEVENT_INSTR_RSM: VBOXVMM_INSTR_RSM(pVCpu, pCtx); break;
12571 case DBGFEVENT_INSTR_CRX_READ: VBOXVMM_INSTR_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12572 case DBGFEVENT_INSTR_CRX_WRITE: VBOXVMM_INSTR_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12573 case DBGFEVENT_INSTR_DRX_READ: VBOXVMM_INSTR_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12574 case DBGFEVENT_INSTR_DRX_WRITE: VBOXVMM_INSTR_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12575 case DBGFEVENT_INSTR_RDMSR: VBOXVMM_INSTR_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12576 case DBGFEVENT_INSTR_WRMSR: VBOXVMM_INSTR_WRMSR(pVCpu, pCtx, pCtx->ecx,
12577 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12578 case DBGFEVENT_INSTR_MWAIT: VBOXVMM_INSTR_MWAIT(pVCpu, pCtx); break;
12579 case DBGFEVENT_INSTR_MONITOR: VBOXVMM_INSTR_MONITOR(pVCpu, pCtx); break;
12580 case DBGFEVENT_INSTR_PAUSE: VBOXVMM_INSTR_PAUSE(pVCpu, pCtx); break;
12581 case DBGFEVENT_INSTR_SGDT: VBOXVMM_INSTR_SGDT(pVCpu, pCtx); break;
12582 case DBGFEVENT_INSTR_SIDT: VBOXVMM_INSTR_SIDT(pVCpu, pCtx); break;
12583 case DBGFEVENT_INSTR_LGDT: VBOXVMM_INSTR_LGDT(pVCpu, pCtx); break;
12584 case DBGFEVENT_INSTR_LIDT: VBOXVMM_INSTR_LIDT(pVCpu, pCtx); break;
12585 case DBGFEVENT_INSTR_SLDT: VBOXVMM_INSTR_SLDT(pVCpu, pCtx); break;
12586 case DBGFEVENT_INSTR_STR: VBOXVMM_INSTR_STR(pVCpu, pCtx); break;
12587 case DBGFEVENT_INSTR_LLDT: VBOXVMM_INSTR_LLDT(pVCpu, pCtx); break;
12588 case DBGFEVENT_INSTR_LTR: VBOXVMM_INSTR_LTR(pVCpu, pCtx); break;
12589 case DBGFEVENT_INSTR_RDTSCP: VBOXVMM_INSTR_RDTSCP(pVCpu, pCtx); break;
12590 case DBGFEVENT_INSTR_WBINVD: VBOXVMM_INSTR_WBINVD(pVCpu, pCtx); break;
12591 case DBGFEVENT_INSTR_XSETBV: VBOXVMM_INSTR_XSETBV(pVCpu, pCtx); break;
12592 case DBGFEVENT_INSTR_RDRAND: VBOXVMM_INSTR_RDRAND(pVCpu, pCtx); break;
12593 case DBGFEVENT_INSTR_RDSEED: VBOXVMM_INSTR_RDSEED(pVCpu, pCtx); break;
12594 case DBGFEVENT_INSTR_XSAVES: VBOXVMM_INSTR_XSAVES(pVCpu, pCtx); break;
12595 case DBGFEVENT_INSTR_XRSTORS: VBOXVMM_INSTR_XRSTORS(pVCpu, pCtx); break;
12596 case DBGFEVENT_INSTR_VMM_CALL: VBOXVMM_INSTR_VMM_CALL(pVCpu, pCtx); break;
12597 case DBGFEVENT_INSTR_VMX_VMCLEAR: VBOXVMM_INSTR_VMX_VMCLEAR(pVCpu, pCtx); break;
12598 case DBGFEVENT_INSTR_VMX_VMLAUNCH: VBOXVMM_INSTR_VMX_VMLAUNCH(pVCpu, pCtx); break;
12599 case DBGFEVENT_INSTR_VMX_VMPTRLD: VBOXVMM_INSTR_VMX_VMPTRLD(pVCpu, pCtx); break;
12600 case DBGFEVENT_INSTR_VMX_VMPTRST: VBOXVMM_INSTR_VMX_VMPTRST(pVCpu, pCtx); break;
12601 case DBGFEVENT_INSTR_VMX_VMREAD: VBOXVMM_INSTR_VMX_VMREAD(pVCpu, pCtx); break;
12602 case DBGFEVENT_INSTR_VMX_VMRESUME: VBOXVMM_INSTR_VMX_VMRESUME(pVCpu, pCtx); break;
12603 case DBGFEVENT_INSTR_VMX_VMWRITE: VBOXVMM_INSTR_VMX_VMWRITE(pVCpu, pCtx); break;
12604 case DBGFEVENT_INSTR_VMX_VMXOFF: VBOXVMM_INSTR_VMX_VMXOFF(pVCpu, pCtx); break;
12605 case DBGFEVENT_INSTR_VMX_VMXON: VBOXVMM_INSTR_VMX_VMXON(pVCpu, pCtx); break;
12606 case DBGFEVENT_INSTR_VMX_INVEPT: VBOXVMM_INSTR_VMX_INVEPT(pVCpu, pCtx); break;
12607 case DBGFEVENT_INSTR_VMX_INVVPID: VBOXVMM_INSTR_VMX_INVVPID(pVCpu, pCtx); break;
12608 case DBGFEVENT_INSTR_VMX_INVPCID: VBOXVMM_INSTR_VMX_INVPCID(pVCpu, pCtx); break;
12609 case DBGFEVENT_INSTR_VMX_VMFUNC: VBOXVMM_INSTR_VMX_VMFUNC(pVCpu, pCtx); break;
12610 default: AssertMsgFailed(("enmEvent1=%d uExitReason=%d\n", enmEvent1, uExitReason)); break;
12611 }
12612 switch (enmEvent2)
12613 {
12614 /** @todo consider which extra parameters would be helpful for each probe. */
12615 case DBGFEVENT_END: break;
12616 case DBGFEVENT_EXIT_TASK_SWITCH: VBOXVMM_EXIT_TASK_SWITCH(pVCpu, pCtx); break;
12617 case DBGFEVENT_EXIT_CPUID: VBOXVMM_EXIT_CPUID(pVCpu, pCtx, pCtx->eax, pCtx->ecx); break;
12618 case DBGFEVENT_EXIT_GETSEC: VBOXVMM_EXIT_GETSEC(pVCpu, pCtx); break;
12619 case DBGFEVENT_EXIT_HALT: VBOXVMM_EXIT_HALT(pVCpu, pCtx); break;
12620 case DBGFEVENT_EXIT_INVD: VBOXVMM_EXIT_INVD(pVCpu, pCtx); break;
12621 case DBGFEVENT_EXIT_INVLPG: VBOXVMM_EXIT_INVLPG(pVCpu, pCtx); break;
12622 case DBGFEVENT_EXIT_RDPMC: VBOXVMM_EXIT_RDPMC(pVCpu, pCtx); break;
12623 case DBGFEVENT_EXIT_RDTSC: VBOXVMM_EXIT_RDTSC(pVCpu, pCtx); break;
12624 case DBGFEVENT_EXIT_RSM: VBOXVMM_EXIT_RSM(pVCpu, pCtx); break;
12625 case DBGFEVENT_EXIT_CRX_READ: VBOXVMM_EXIT_CRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12626 case DBGFEVENT_EXIT_CRX_WRITE: VBOXVMM_EXIT_CRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12627 case DBGFEVENT_EXIT_DRX_READ: VBOXVMM_EXIT_DRX_READ(pVCpu, pCtx, (uint8_t)uEventArg); break;
12628 case DBGFEVENT_EXIT_DRX_WRITE: VBOXVMM_EXIT_DRX_WRITE(pVCpu, pCtx, (uint8_t)uEventArg); break;
12629 case DBGFEVENT_EXIT_RDMSR: VBOXVMM_EXIT_RDMSR(pVCpu, pCtx, pCtx->ecx); break;
12630 case DBGFEVENT_EXIT_WRMSR: VBOXVMM_EXIT_WRMSR(pVCpu, pCtx, pCtx->ecx,
12631 RT_MAKE_U64(pCtx->eax, pCtx->edx)); break;
12632 case DBGFEVENT_EXIT_MWAIT: VBOXVMM_EXIT_MWAIT(pVCpu, pCtx); break;
12633 case DBGFEVENT_EXIT_MONITOR: VBOXVMM_EXIT_MONITOR(pVCpu, pCtx); break;
12634 case DBGFEVENT_EXIT_PAUSE: VBOXVMM_EXIT_PAUSE(pVCpu, pCtx); break;
12635 case DBGFEVENT_EXIT_SGDT: VBOXVMM_EXIT_SGDT(pVCpu, pCtx); break;
12636 case DBGFEVENT_EXIT_SIDT: VBOXVMM_EXIT_SIDT(pVCpu, pCtx); break;
12637 case DBGFEVENT_EXIT_LGDT: VBOXVMM_EXIT_LGDT(pVCpu, pCtx); break;
12638 case DBGFEVENT_EXIT_LIDT: VBOXVMM_EXIT_LIDT(pVCpu, pCtx); break;
12639 case DBGFEVENT_EXIT_SLDT: VBOXVMM_EXIT_SLDT(pVCpu, pCtx); break;
12640 case DBGFEVENT_EXIT_STR: VBOXVMM_EXIT_STR(pVCpu, pCtx); break;
12641 case DBGFEVENT_EXIT_LLDT: VBOXVMM_EXIT_LLDT(pVCpu, pCtx); break;
12642 case DBGFEVENT_EXIT_LTR: VBOXVMM_EXIT_LTR(pVCpu, pCtx); break;
12643 case DBGFEVENT_EXIT_RDTSCP: VBOXVMM_EXIT_RDTSCP(pVCpu, pCtx); break;
12644 case DBGFEVENT_EXIT_WBINVD: VBOXVMM_EXIT_WBINVD(pVCpu, pCtx); break;
12645 case DBGFEVENT_EXIT_XSETBV: VBOXVMM_EXIT_XSETBV(pVCpu, pCtx); break;
12646 case DBGFEVENT_EXIT_RDRAND: VBOXVMM_EXIT_RDRAND(pVCpu, pCtx); break;
12647 case DBGFEVENT_EXIT_RDSEED: VBOXVMM_EXIT_RDSEED(pVCpu, pCtx); break;
12648 case DBGFEVENT_EXIT_XSAVES: VBOXVMM_EXIT_XSAVES(pVCpu, pCtx); break;
12649 case DBGFEVENT_EXIT_XRSTORS: VBOXVMM_EXIT_XRSTORS(pVCpu, pCtx); break;
12650 case DBGFEVENT_EXIT_VMM_CALL: VBOXVMM_EXIT_VMM_CALL(pVCpu, pCtx); break;
12651 case DBGFEVENT_EXIT_VMX_VMCLEAR: VBOXVMM_EXIT_VMX_VMCLEAR(pVCpu, pCtx); break;
12652 case DBGFEVENT_EXIT_VMX_VMLAUNCH: VBOXVMM_EXIT_VMX_VMLAUNCH(pVCpu, pCtx); break;
12653 case DBGFEVENT_EXIT_VMX_VMPTRLD: VBOXVMM_EXIT_VMX_VMPTRLD(pVCpu, pCtx); break;
12654 case DBGFEVENT_EXIT_VMX_VMPTRST: VBOXVMM_EXIT_VMX_VMPTRST(pVCpu, pCtx); break;
12655 case DBGFEVENT_EXIT_VMX_VMREAD: VBOXVMM_EXIT_VMX_VMREAD(pVCpu, pCtx); break;
12656 case DBGFEVENT_EXIT_VMX_VMRESUME: VBOXVMM_EXIT_VMX_VMRESUME(pVCpu, pCtx); break;
12657 case DBGFEVENT_EXIT_VMX_VMWRITE: VBOXVMM_EXIT_VMX_VMWRITE(pVCpu, pCtx); break;
12658 case DBGFEVENT_EXIT_VMX_VMXOFF: VBOXVMM_EXIT_VMX_VMXOFF(pVCpu, pCtx); break;
12659 case DBGFEVENT_EXIT_VMX_VMXON: VBOXVMM_EXIT_VMX_VMXON(pVCpu, pCtx); break;
12660 case DBGFEVENT_EXIT_VMX_INVEPT: VBOXVMM_EXIT_VMX_INVEPT(pVCpu, pCtx); break;
12661 case DBGFEVENT_EXIT_VMX_INVVPID: VBOXVMM_EXIT_VMX_INVVPID(pVCpu, pCtx); break;
12662 case DBGFEVENT_EXIT_VMX_INVPCID: VBOXVMM_EXIT_VMX_INVPCID(pVCpu, pCtx); break;
12663 case DBGFEVENT_EXIT_VMX_VMFUNC: VBOXVMM_EXIT_VMX_VMFUNC(pVCpu, pCtx); break;
12664 case DBGFEVENT_EXIT_VMX_EPT_MISCONFIG: VBOXVMM_EXIT_VMX_EPT_MISCONFIG(pVCpu, pCtx); break;
12665 case DBGFEVENT_EXIT_VMX_EPT_VIOLATION: VBOXVMM_EXIT_VMX_EPT_VIOLATION(pVCpu, pCtx); break;
12666 case DBGFEVENT_EXIT_VMX_VAPIC_ACCESS: VBOXVMM_EXIT_VMX_VAPIC_ACCESS(pVCpu, pCtx); break;
12667 case DBGFEVENT_EXIT_VMX_VAPIC_WRITE: VBOXVMM_EXIT_VMX_VAPIC_WRITE(pVCpu, pCtx); break;
12668 default: AssertMsgFailed(("enmEvent2=%d uExitReason=%d\n", enmEvent2, uExitReason)); break;
12669 }
12670 }
12671
12672 /*
12673 * Fire of the DBGF event, if enabled (our check here is just a quick one,
12674 * the DBGF call will do a full check).
12675 *
12676 * Note! DBGF sets DBGFEVENT_INTERRUPT_SOFTWARE in the bitmap.
12677 * Note! If we have to events, we prioritize the first, i.e. the instruction
12678 * one, in order to avoid event nesting.
12679 */
12680 PVM pVM = pVCpu->CTX_SUFF(pVM);
12681 if ( enmEvent1 != DBGFEVENT_END
12682 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent1))
12683 {
12684 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12685 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent1, DBGFEVENTCTX_HM, 1, uEventArg);
12686 if (rcStrict != VINF_SUCCESS)
12687 return rcStrict;
12688 }
12689 else if ( enmEvent2 != DBGFEVENT_END
12690 && DBGF_IS_EVENT_ENABLED(pVM, enmEvent2))
12691 {
12692 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12693 VBOXSTRICTRC rcStrict = DBGFEventGenericWithArgs(pVM, pVCpu, enmEvent2, DBGFEVENTCTX_HM, 1, uEventArg);
12694 if (rcStrict != VINF_SUCCESS)
12695 return rcStrict;
12696 }
12697
12698 return VINF_SUCCESS;
12699}
12700
12701
12702/**
12703 * Single-stepping VM-exit filtering.
12704 *
12705 * This is preprocessing the VM-exits and deciding whether we've gotten far
12706 * enough to return VINF_EM_DBG_STEPPED already. If not, normal VM-exit
12707 * handling is performed.
12708 *
12709 * @returns Strict VBox status code (i.e. informational status codes too).
12710 * @param pVCpu The cross context virtual CPU structure of the calling EMT.
12711 * @param pVmxTransient The VMX-transient structure.
12712 * @param pDbgState The debug state.
12713 */
12714DECLINLINE(VBOXSTRICTRC) hmR0VmxRunDebugHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PVMXRUNDBGSTATE pDbgState)
12715{
12716 /*
12717 * Expensive (saves context) generic dtrace VM-exit probe.
12718 */
12719 uint32_t const uExitReason = pVmxTransient->uExitReason;
12720 if (!VBOXVMM_R0_HMVMX_VMEXIT_ENABLED())
12721 { /* more likely */ }
12722 else
12723 {
12724 hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
12725 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
12726 AssertRC(rc);
12727 VBOXVMM_R0_HMVMX_VMEXIT(pVCpu, &pVCpu->cpum.GstCtx, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
12728 }
12729
12730 /*
12731 * Check for host NMI, just to get that out of the way.
12732 */
12733 if (uExitReason != VMX_EXIT_XCPT_OR_NMI)
12734 { /* normally likely */ }
12735 else
12736 {
12737 int rc2 = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
12738 AssertRCReturn(rc2, rc2);
12739 uint32_t const uIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
12740 if (uIntType == VMX_EXIT_INT_INFO_TYPE_NMI)
12741 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
12742 }
12743
12744 /*
12745 * Check for single stepping event if we're stepping.
12746 */
12747 if (pVCpu->hm.s.fSingleInstruction)
12748 {
12749 switch (uExitReason)
12750 {
12751 case VMX_EXIT_MTF:
12752 return hmR0VmxExitMtf(pVCpu, pVmxTransient);
12753
12754 /* Various events: */
12755 case VMX_EXIT_XCPT_OR_NMI:
12756 case VMX_EXIT_EXT_INT:
12757 case VMX_EXIT_TRIPLE_FAULT:
12758 case VMX_EXIT_INT_WINDOW:
12759 case VMX_EXIT_NMI_WINDOW:
12760 case VMX_EXIT_TASK_SWITCH:
12761 case VMX_EXIT_TPR_BELOW_THRESHOLD:
12762 case VMX_EXIT_APIC_ACCESS:
12763 case VMX_EXIT_EPT_VIOLATION:
12764 case VMX_EXIT_EPT_MISCONFIG:
12765 case VMX_EXIT_PREEMPT_TIMER:
12766
12767 /* Instruction specific VM-exits: */
12768 case VMX_EXIT_CPUID:
12769 case VMX_EXIT_GETSEC:
12770 case VMX_EXIT_HLT:
12771 case VMX_EXIT_INVD:
12772 case VMX_EXIT_INVLPG:
12773 case VMX_EXIT_RDPMC:
12774 case VMX_EXIT_RDTSC:
12775 case VMX_EXIT_RSM:
12776 case VMX_EXIT_VMCALL:
12777 case VMX_EXIT_VMCLEAR:
12778 case VMX_EXIT_VMLAUNCH:
12779 case VMX_EXIT_VMPTRLD:
12780 case VMX_EXIT_VMPTRST:
12781 case VMX_EXIT_VMREAD:
12782 case VMX_EXIT_VMRESUME:
12783 case VMX_EXIT_VMWRITE:
12784 case VMX_EXIT_VMXOFF:
12785 case VMX_EXIT_VMXON:
12786 case VMX_EXIT_MOV_CRX:
12787 case VMX_EXIT_MOV_DRX:
12788 case VMX_EXIT_IO_INSTR:
12789 case VMX_EXIT_RDMSR:
12790 case VMX_EXIT_WRMSR:
12791 case VMX_EXIT_MWAIT:
12792 case VMX_EXIT_MONITOR:
12793 case VMX_EXIT_PAUSE:
12794 case VMX_EXIT_GDTR_IDTR_ACCESS:
12795 case VMX_EXIT_LDTR_TR_ACCESS:
12796 case VMX_EXIT_INVEPT:
12797 case VMX_EXIT_RDTSCP:
12798 case VMX_EXIT_INVVPID:
12799 case VMX_EXIT_WBINVD:
12800 case VMX_EXIT_XSETBV:
12801 case VMX_EXIT_RDRAND:
12802 case VMX_EXIT_INVPCID:
12803 case VMX_EXIT_VMFUNC:
12804 case VMX_EXIT_RDSEED:
12805 case VMX_EXIT_XSAVES:
12806 case VMX_EXIT_XRSTORS:
12807 {
12808 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12809 AssertRCReturn(rc, rc);
12810 if ( pVCpu->cpum.GstCtx.rip != pDbgState->uRipStart
12811 || pVCpu->cpum.GstCtx.cs.Sel != pDbgState->uCsStart)
12812 return VINF_EM_DBG_STEPPED;
12813 break;
12814 }
12815
12816 /* Errors and unexpected events: */
12817 case VMX_EXIT_INIT_SIGNAL:
12818 case VMX_EXIT_SIPI:
12819 case VMX_EXIT_IO_SMI:
12820 case VMX_EXIT_SMI:
12821 case VMX_EXIT_ERR_INVALID_GUEST_STATE:
12822 case VMX_EXIT_ERR_MSR_LOAD:
12823 case VMX_EXIT_ERR_MACHINE_CHECK:
12824 case VMX_EXIT_PML_FULL:
12825 case VMX_EXIT_VIRTUALIZED_EOI:
12826 case VMX_EXIT_APIC_WRITE: /* Some talk about this being fault like, so I guess we must process it? */
12827 break;
12828
12829 default:
12830 AssertMsgFailed(("Unexpected VM-exit=%#x\n", uExitReason));
12831 break;
12832 }
12833 }
12834
12835 /*
12836 * Check for debugger event breakpoints and dtrace probes.
12837 */
12838 if ( uExitReason < RT_ELEMENTS(pDbgState->bmExitsToCheck) * 32U
12839 && ASMBitTest(pDbgState->bmExitsToCheck, uExitReason) )
12840 {
12841 VBOXSTRICTRC rcStrict = hmR0VmxHandleExitDtraceEvents(pVCpu, pVmxTransient, uExitReason);
12842 if (rcStrict != VINF_SUCCESS)
12843 return rcStrict;
12844 }
12845
12846 /*
12847 * Normal processing.
12848 */
12849#ifdef HMVMX_USE_FUNCTION_TABLE
12850 return g_apfnVMExitHandlers[uExitReason](pVCpu, pVmxTransient);
12851#else
12852 return hmR0VmxHandleExit(pVCpu, pVmxTransient, uExitReason);
12853#endif
12854}
12855
12856
12857/**
12858 * Single steps guest code using hardware-assisted VMX.
12859 *
12860 * This is -not- the same as the guest single-stepping itself (say using EFLAGS.TF)
12861 * but single-stepping through the hypervisor debugger.
12862 *
12863 * @returns Strict VBox status code (i.e. informational status codes too).
12864 * @param pVCpu The cross context virtual CPU structure.
12865 * @param pcLoops Pointer to the number of executed loops.
12866 *
12867 * @note Mostly the same as hmR0VmxRunGuestCodeNormal().
12868 */
12869static VBOXSTRICTRC hmR0VmxRunGuestCodeDebug(PVMCPU pVCpu, uint32_t *pcLoops)
12870{
12871 uint32_t const cMaxResumeLoops = pVCpu->CTX_SUFF(pVM)->hm.s.cMaxResumeLoops;
12872 Assert(pcLoops);
12873 Assert(*pcLoops <= cMaxResumeLoops);
12874
12875 VMXTRANSIENT VmxTransient;
12876 RT_ZERO(VmxTransient);
12877 VmxTransient.pVmcsInfo = hmGetVmxActiveVmcsInfo(pVCpu);
12878
12879 /* Set HMCPU indicators. */
12880 bool const fSavedSingleInstruction = pVCpu->hm.s.fSingleInstruction;
12881 pVCpu->hm.s.fSingleInstruction = pVCpu->hm.s.fSingleInstruction || DBGFIsStepping(pVCpu);
12882 pVCpu->hm.s.fDebugWantRdTscExit = false;
12883 pVCpu->hm.s.fUsingDebugLoop = true;
12884
12885 /* State we keep to help modify and later restore the VMCS fields we alter, and for detecting steps. */
12886 VMXRUNDBGSTATE DbgState;
12887 hmR0VmxRunDebugStateInit(pVCpu, &VmxTransient, &DbgState);
12888 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12889
12890 /*
12891 * The loop.
12892 */
12893 VBOXSTRICTRC rcStrict = VERR_INTERNAL_ERROR_5;
12894 for (;;)
12895 {
12896 Assert(!HMR0SuspendPending());
12897 HMVMX_ASSERT_CPU_SAFE(pVCpu);
12898 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatEntry, x);
12899 bool fStepping = pVCpu->hm.s.fSingleInstruction;
12900
12901 /* Set up VM-execution controls the next two can respond to. */
12902 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12903
12904 /*
12905 * Preparatory work for running guest code, this may force us to
12906 * return to ring-3.
12907 *
12908 * Warning! This bugger disables interrupts on VINF_SUCCESS!
12909 */
12910 rcStrict = hmR0VmxPreRunGuest(pVCpu, &VmxTransient, fStepping);
12911 if (rcStrict != VINF_SUCCESS)
12912 break;
12913
12914 /* Interrupts are disabled at this point! */
12915 hmR0VmxPreRunGuestCommitted(pVCpu, &VmxTransient);
12916
12917 /* Override any obnoxious code in the above two calls. */
12918 hmR0VmxPreRunGuestDebugStateApply(pVCpu, &VmxTransient, &DbgState);
12919
12920 /*
12921 * Finally execute the guest.
12922 */
12923 int rcRun = hmR0VmxRunGuest(pVCpu, &VmxTransient);
12924
12925 hmR0VmxPostRunGuest(pVCpu, &VmxTransient, rcRun);
12926 /* Interrupts are re-enabled at this point! */
12927
12928 /* Check for errors with running the VM (VMLAUNCH/VMRESUME). */
12929 if (RT_SUCCESS(rcRun))
12930 { /* very likely */ }
12931 else
12932 {
12933 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatPreExit, x);
12934 hmR0VmxReportWorldSwitchError(pVCpu, rcRun, &VmxTransient);
12935 return rcRun;
12936 }
12937
12938 /* Profile the VM-exit. */
12939 AssertMsg(VmxTransient.uExitReason <= VMX_EXIT_MAX, ("%#x\n", VmxTransient.uExitReason));
12940 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitAll);
12941 STAM_COUNTER_INC(&pVCpu->hm.s.paStatExitReasonR0[VmxTransient.uExitReason & MASK_EXITREASON_STAT]);
12942 STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatPreExit, &pVCpu->hm.s.StatExitHandling, x);
12943 HMVMX_START_EXIT_DISPATCH_PROF();
12944
12945 VBOXVMM_R0_HMVMX_VMEXIT_NOCTX(pVCpu, &pVCpu->cpum.GstCtx, VmxTransient.uExitReason);
12946
12947 /*
12948 * Handle the VM-exit - we quit earlier on certain VM-exits, see hmR0VmxHandleExitDebug().
12949 */
12950 rcStrict = hmR0VmxRunDebugHandleExit(pVCpu, &VmxTransient, &DbgState);
12951 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitHandling, x);
12952 if (rcStrict != VINF_SUCCESS)
12953 break;
12954 if (++(*pcLoops) > cMaxResumeLoops)
12955 {
12956 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchMaxResumeLoops);
12957 rcStrict = VINF_EM_RAW_INTERRUPT;
12958 break;
12959 }
12960
12961 /*
12962 * Stepping: Did the RIP change, if so, consider it a single step.
12963 * Otherwise, make sure one of the TFs gets set.
12964 */
12965 if (fStepping)
12966 {
12967 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
12968 AssertRC(rc);
12969 if ( pVCpu->cpum.GstCtx.rip != DbgState.uRipStart
12970 || pVCpu->cpum.GstCtx.cs.Sel != DbgState.uCsStart)
12971 {
12972 rcStrict = VINF_EM_DBG_STEPPED;
12973 break;
12974 }
12975 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
12976 }
12977
12978 /*
12979 * Update when dtrace settings changes (DBGF kicks us, so no need to check).
12980 */
12981 if (VBOXVMM_GET_SETTINGS_SEQ_NO() != DbgState.uDtraceSettingsSeqNo)
12982 hmR0VmxPreRunGuestDebugStateUpdate(pVCpu, &VmxTransient, &DbgState);
12983 }
12984
12985 /*
12986 * Clear the X86_EFL_TF if necessary.
12987 */
12988 if (pVCpu->hm.s.fClearTrapFlag)
12989 {
12990 int rc = hmR0VmxImportGuestState(pVCpu, VmxTransient.pVmcsInfo, CPUMCTX_EXTRN_RFLAGS);
12991 AssertRC(rc);
12992 pVCpu->hm.s.fClearTrapFlag = false;
12993 pVCpu->cpum.GstCtx.eflags.Bits.u1TF = 0;
12994 }
12995 /** @todo there seems to be issues with the resume flag when the monitor trap
12996 * flag is pending without being used. Seen early in bios init when
12997 * accessing APIC page in protected mode. */
12998
12999 /*
13000 * Restore VM-exit control settings as we may not re-enter this function the
13001 * next time around.
13002 */
13003 rcStrict = hmR0VmxRunDebugStateRevert(pVCpu, &VmxTransient, &DbgState, rcStrict);
13004
13005 /* Restore HMCPU indicators. */
13006 pVCpu->hm.s.fUsingDebugLoop = false;
13007 pVCpu->hm.s.fDebugWantRdTscExit = false;
13008 pVCpu->hm.s.fSingleInstruction = fSavedSingleInstruction;
13009
13010 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatEntry, x);
13011 return rcStrict;
13012}
13013
13014
13015/** @} */
13016
13017
13018/**
13019 * Checks if any expensive dtrace probes are enabled and we should go to the
13020 * debug loop.
13021 *
13022 * @returns true if we should use debug loop, false if not.
13023 */
13024static bool hmR0VmxAnyExpensiveProbesEnabled(void)
13025{
13026 /* It's probably faster to OR the raw 32-bit counter variables together.
13027 Since the variables are in an array and the probes are next to one
13028 another (more or less), we have good locality. So, better read
13029 eight-nine cache lines ever time and only have one conditional, than
13030 128+ conditionals, right? */
13031 return ( VBOXVMM_R0_HMVMX_VMEXIT_ENABLED_RAW() /* expensive too due to context */
13032 | VBOXVMM_XCPT_DE_ENABLED_RAW()
13033 | VBOXVMM_XCPT_DB_ENABLED_RAW()
13034 | VBOXVMM_XCPT_BP_ENABLED_RAW()
13035 | VBOXVMM_XCPT_OF_ENABLED_RAW()
13036 | VBOXVMM_XCPT_BR_ENABLED_RAW()
13037 | VBOXVMM_XCPT_UD_ENABLED_RAW()
13038 | VBOXVMM_XCPT_NM_ENABLED_RAW()
13039 | VBOXVMM_XCPT_DF_ENABLED_RAW()
13040 | VBOXVMM_XCPT_TS_ENABLED_RAW()
13041 | VBOXVMM_XCPT_NP_ENABLED_RAW()
13042 | VBOXVMM_XCPT_SS_ENABLED_RAW()
13043 | VBOXVMM_XCPT_GP_ENABLED_RAW()
13044 | VBOXVMM_XCPT_PF_ENABLED_RAW()
13045 | VBOXVMM_XCPT_MF_ENABLED_RAW()
13046 | VBOXVMM_XCPT_AC_ENABLED_RAW()
13047 | VBOXVMM_XCPT_XF_ENABLED_RAW()
13048 | VBOXVMM_XCPT_VE_ENABLED_RAW()
13049 | VBOXVMM_XCPT_SX_ENABLED_RAW()
13050 | VBOXVMM_INT_SOFTWARE_ENABLED_RAW()
13051 | VBOXVMM_INT_HARDWARE_ENABLED_RAW()
13052 ) != 0
13053 || ( VBOXVMM_INSTR_HALT_ENABLED_RAW()
13054 | VBOXVMM_INSTR_MWAIT_ENABLED_RAW()
13055 | VBOXVMM_INSTR_MONITOR_ENABLED_RAW()
13056 | VBOXVMM_INSTR_CPUID_ENABLED_RAW()
13057 | VBOXVMM_INSTR_INVD_ENABLED_RAW()
13058 | VBOXVMM_INSTR_WBINVD_ENABLED_RAW()
13059 | VBOXVMM_INSTR_INVLPG_ENABLED_RAW()
13060 | VBOXVMM_INSTR_RDTSC_ENABLED_RAW()
13061 | VBOXVMM_INSTR_RDTSCP_ENABLED_RAW()
13062 | VBOXVMM_INSTR_RDPMC_ENABLED_RAW()
13063 | VBOXVMM_INSTR_RDMSR_ENABLED_RAW()
13064 | VBOXVMM_INSTR_WRMSR_ENABLED_RAW()
13065 | VBOXVMM_INSTR_CRX_READ_ENABLED_RAW()
13066 | VBOXVMM_INSTR_CRX_WRITE_ENABLED_RAW()
13067 | VBOXVMM_INSTR_DRX_READ_ENABLED_RAW()
13068 | VBOXVMM_INSTR_DRX_WRITE_ENABLED_RAW()
13069 | VBOXVMM_INSTR_PAUSE_ENABLED_RAW()
13070 | VBOXVMM_INSTR_XSETBV_ENABLED_RAW()
13071 | VBOXVMM_INSTR_SIDT_ENABLED_RAW()
13072 | VBOXVMM_INSTR_LIDT_ENABLED_RAW()
13073 | VBOXVMM_INSTR_SGDT_ENABLED_RAW()
13074 | VBOXVMM_INSTR_LGDT_ENABLED_RAW()
13075 | VBOXVMM_INSTR_SLDT_ENABLED_RAW()
13076 | VBOXVMM_INSTR_LLDT_ENABLED_RAW()
13077 | VBOXVMM_INSTR_STR_ENABLED_RAW()
13078 | VBOXVMM_INSTR_LTR_ENABLED_RAW()
13079 | VBOXVMM_INSTR_GETSEC_ENABLED_RAW()
13080 | VBOXVMM_INSTR_RSM_ENABLED_RAW()
13081 | VBOXVMM_INSTR_RDRAND_ENABLED_RAW()
13082 | VBOXVMM_INSTR_RDSEED_ENABLED_RAW()
13083 | VBOXVMM_INSTR_XSAVES_ENABLED_RAW()
13084 | VBOXVMM_INSTR_XRSTORS_ENABLED_RAW()
13085 | VBOXVMM_INSTR_VMM_CALL_ENABLED_RAW()
13086 | VBOXVMM_INSTR_VMX_VMCLEAR_ENABLED_RAW()
13087 | VBOXVMM_INSTR_VMX_VMLAUNCH_ENABLED_RAW()
13088 | VBOXVMM_INSTR_VMX_VMPTRLD_ENABLED_RAW()
13089 | VBOXVMM_INSTR_VMX_VMPTRST_ENABLED_RAW()
13090 | VBOXVMM_INSTR_VMX_VMREAD_ENABLED_RAW()
13091 | VBOXVMM_INSTR_VMX_VMRESUME_ENABLED_RAW()
13092 | VBOXVMM_INSTR_VMX_VMWRITE_ENABLED_RAW()
13093 | VBOXVMM_INSTR_VMX_VMXOFF_ENABLED_RAW()
13094 | VBOXVMM_INSTR_VMX_VMXON_ENABLED_RAW()
13095 | VBOXVMM_INSTR_VMX_VMFUNC_ENABLED_RAW()
13096 | VBOXVMM_INSTR_VMX_INVEPT_ENABLED_RAW()
13097 | VBOXVMM_INSTR_VMX_INVVPID_ENABLED_RAW()
13098 | VBOXVMM_INSTR_VMX_INVPCID_ENABLED_RAW()
13099 ) != 0
13100 || ( VBOXVMM_EXIT_TASK_SWITCH_ENABLED_RAW()
13101 | VBOXVMM_EXIT_HALT_ENABLED_RAW()
13102 | VBOXVMM_EXIT_MWAIT_ENABLED_RAW()
13103 | VBOXVMM_EXIT_MONITOR_ENABLED_RAW()
13104 | VBOXVMM_EXIT_CPUID_ENABLED_RAW()
13105 | VBOXVMM_EXIT_INVD_ENABLED_RAW()
13106 | VBOXVMM_EXIT_WBINVD_ENABLED_RAW()
13107 | VBOXVMM_EXIT_INVLPG_ENABLED_RAW()
13108 | VBOXVMM_EXIT_RDTSC_ENABLED_RAW()
13109 | VBOXVMM_EXIT_RDTSCP_ENABLED_RAW()
13110 | VBOXVMM_EXIT_RDPMC_ENABLED_RAW()
13111 | VBOXVMM_EXIT_RDMSR_ENABLED_RAW()
13112 | VBOXVMM_EXIT_WRMSR_ENABLED_RAW()
13113 | VBOXVMM_EXIT_CRX_READ_ENABLED_RAW()
13114 | VBOXVMM_EXIT_CRX_WRITE_ENABLED_RAW()
13115 | VBOXVMM_EXIT_DRX_READ_ENABLED_RAW()
13116 | VBOXVMM_EXIT_DRX_WRITE_ENABLED_RAW()
13117 | VBOXVMM_EXIT_PAUSE_ENABLED_RAW()
13118 | VBOXVMM_EXIT_XSETBV_ENABLED_RAW()
13119 | VBOXVMM_EXIT_SIDT_ENABLED_RAW()
13120 | VBOXVMM_EXIT_LIDT_ENABLED_RAW()
13121 | VBOXVMM_EXIT_SGDT_ENABLED_RAW()
13122 | VBOXVMM_EXIT_LGDT_ENABLED_RAW()
13123 | VBOXVMM_EXIT_SLDT_ENABLED_RAW()
13124 | VBOXVMM_EXIT_LLDT_ENABLED_RAW()
13125 | VBOXVMM_EXIT_STR_ENABLED_RAW()
13126 | VBOXVMM_EXIT_LTR_ENABLED_RAW()
13127 | VBOXVMM_EXIT_GETSEC_ENABLED_RAW()
13128 | VBOXVMM_EXIT_RSM_ENABLED_RAW()
13129 | VBOXVMM_EXIT_RDRAND_ENABLED_RAW()
13130 | VBOXVMM_EXIT_RDSEED_ENABLED_RAW()
13131 | VBOXVMM_EXIT_XSAVES_ENABLED_RAW()
13132 | VBOXVMM_EXIT_XRSTORS_ENABLED_RAW()
13133 | VBOXVMM_EXIT_VMM_CALL_ENABLED_RAW()
13134 | VBOXVMM_EXIT_VMX_VMCLEAR_ENABLED_RAW()
13135 | VBOXVMM_EXIT_VMX_VMLAUNCH_ENABLED_RAW()
13136 | VBOXVMM_EXIT_VMX_VMPTRLD_ENABLED_RAW()
13137 | VBOXVMM_EXIT_VMX_VMPTRST_ENABLED_RAW()
13138 | VBOXVMM_EXIT_VMX_VMREAD_ENABLED_RAW()
13139 | VBOXVMM_EXIT_VMX_VMRESUME_ENABLED_RAW()
13140 | VBOXVMM_EXIT_VMX_VMWRITE_ENABLED_RAW()
13141 | VBOXVMM_EXIT_VMX_VMXOFF_ENABLED_RAW()
13142 | VBOXVMM_EXIT_VMX_VMXON_ENABLED_RAW()
13143 | VBOXVMM_EXIT_VMX_VMFUNC_ENABLED_RAW()
13144 | VBOXVMM_EXIT_VMX_INVEPT_ENABLED_RAW()
13145 | VBOXVMM_EXIT_VMX_INVVPID_ENABLED_RAW()
13146 | VBOXVMM_EXIT_VMX_INVPCID_ENABLED_RAW()
13147 | VBOXVMM_EXIT_VMX_EPT_VIOLATION_ENABLED_RAW()
13148 | VBOXVMM_EXIT_VMX_EPT_MISCONFIG_ENABLED_RAW()
13149 | VBOXVMM_EXIT_VMX_VAPIC_ACCESS_ENABLED_RAW()
13150 | VBOXVMM_EXIT_VMX_VAPIC_WRITE_ENABLED_RAW()
13151 ) != 0;
13152}
13153
13154
13155/**
13156 * Runs the guest using hardware-assisted VMX.
13157 *
13158 * @returns Strict VBox status code (i.e. informational status codes too).
13159 * @param pVCpu The cross context virtual CPU structure.
13160 */
13161VMMR0DECL(VBOXSTRICTRC) VMXR0RunGuestCode(PVMCPU pVCpu)
13162{
13163 AssertPtr(pVCpu);
13164 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
13165 Assert(VMMRZCallRing3IsEnabled(pVCpu));
13166 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13167 HMVMX_ASSERT_PREEMPT_SAFE(pVCpu);
13168
13169 VMMRZCallRing3SetNotification(pVCpu, hmR0VmxCallRing3Callback, pCtx);
13170
13171 VBOXSTRICTRC rcStrict;
13172 uint32_t cLoops = 0;
13173 for (;;)
13174 {
13175#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13176 bool const fInNestedGuestMode = CPUMIsGuestInVmxNonRootMode(pCtx);
13177#else
13178 bool const fInNestedGuestMode = false;
13179#endif
13180 if (!fInNestedGuestMode)
13181 {
13182 if ( !pVCpu->hm.s.fUseDebugLoop
13183 && (!VBOXVMM_ANY_PROBES_ENABLED() || !hmR0VmxAnyExpensiveProbesEnabled())
13184 && !DBGFIsStepping(pVCpu)
13185 && !pVCpu->CTX_SUFF(pVM)->dbgf.ro.cEnabledInt3Breakpoints)
13186 rcStrict = hmR0VmxRunGuestCodeNormal(pVCpu, &cLoops);
13187 else
13188 rcStrict = hmR0VmxRunGuestCodeDebug(pVCpu, &cLoops);
13189 }
13190#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13191 else
13192 rcStrict = hmR0VmxRunGuestCodeNested(pVCpu, &cLoops);
13193
13194 if (rcStrict == VINF_VMX_VMLAUNCH_VMRESUME)
13195 {
13196 Assert(CPUMIsGuestInVmxNonRootMode(pCtx));
13197 continue;
13198 }
13199 if (rcStrict == VINF_VMX_VMEXIT)
13200 {
13201 Assert(!CPUMIsGuestInVmxNonRootMode(pCtx));
13202 continue;
13203 }
13204#endif
13205 break;
13206 }
13207
13208 int const rcLoop = VBOXSTRICTRC_VAL(rcStrict);
13209 switch (rcLoop)
13210 {
13211 case VERR_EM_INTERPRETER: rcStrict = VINF_EM_RAW_EMULATE_INSTR; break;
13212 case VINF_EM_RESET: rcStrict = VINF_EM_TRIPLE_FAULT; break;
13213 }
13214
13215 int rc2 = hmR0VmxExitToRing3(pVCpu, rcStrict);
13216 if (RT_FAILURE(rc2))
13217 {
13218 pVCpu->hm.s.u32HMError = (uint32_t)VBOXSTRICTRC_VAL(rcStrict);
13219 rcStrict = rc2;
13220 }
13221 Assert(!ASMAtomicUoReadU64(&pCtx->fExtrn));
13222 Assert(!VMMRZCallRing3IsNotificationSet(pVCpu));
13223 return rcStrict;
13224}
13225
13226
13227#ifndef HMVMX_USE_FUNCTION_TABLE
13228/**
13229 * Handles a guest VM-exit from hardware-assisted VMX execution.
13230 *
13231 * @returns Strict VBox status code (i.e. informational status codes too).
13232 * @param pVCpu The cross context virtual CPU structure.
13233 * @param pVmxTransient The VMX-transient structure.
13234 */
13235DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExit(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13236{
13237#ifdef DEBUG_ramshankar
13238#define VMEXIT_CALL_RET(a_fSave, a_CallExpr) \
13239 do { \
13240 if (a_fSave != 0) \
13241 hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL); \
13242 VBOXSTRICTRC rcStrict = a_CallExpr; \
13243 if (a_fSave != 0) \
13244 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST); \
13245 return rcStrict; \
13246 } while (0)
13247#else
13248# define VMEXIT_CALL_RET(a_fSave, a_CallExpr) return a_CallExpr
13249#endif
13250 uint32_t const uExitReason = pVmxTransient->uExitReason;
13251 switch (uExitReason)
13252 {
13253 case VMX_EXIT_EPT_MISCONFIG: VMEXIT_CALL_RET(0, hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient));
13254 case VMX_EXIT_EPT_VIOLATION: VMEXIT_CALL_RET(0, hmR0VmxExitEptViolation(pVCpu, pVmxTransient));
13255 case VMX_EXIT_IO_INSTR: VMEXIT_CALL_RET(0, hmR0VmxExitIoInstr(pVCpu, pVmxTransient));
13256 case VMX_EXIT_CPUID: VMEXIT_CALL_RET(0, hmR0VmxExitCpuid(pVCpu, pVmxTransient));
13257 case VMX_EXIT_RDTSC: VMEXIT_CALL_RET(0, hmR0VmxExitRdtsc(pVCpu, pVmxTransient));
13258 case VMX_EXIT_RDTSCP: VMEXIT_CALL_RET(0, hmR0VmxExitRdtscp(pVCpu, pVmxTransient));
13259 case VMX_EXIT_APIC_ACCESS: VMEXIT_CALL_RET(0, hmR0VmxExitApicAccess(pVCpu, pVmxTransient));
13260 case VMX_EXIT_XCPT_OR_NMI: VMEXIT_CALL_RET(0, hmR0VmxExitXcptOrNmi(pVCpu, pVmxTransient));
13261 case VMX_EXIT_MOV_CRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovCRx(pVCpu, pVmxTransient));
13262 case VMX_EXIT_EXT_INT: VMEXIT_CALL_RET(0, hmR0VmxExitExtInt(pVCpu, pVmxTransient));
13263 case VMX_EXIT_INT_WINDOW: VMEXIT_CALL_RET(0, hmR0VmxExitIntWindow(pVCpu, pVmxTransient));
13264 case VMX_EXIT_TPR_BELOW_THRESHOLD: VMEXIT_CALL_RET(0, hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient));
13265 case VMX_EXIT_MWAIT: VMEXIT_CALL_RET(0, hmR0VmxExitMwait(pVCpu, pVmxTransient));
13266 case VMX_EXIT_MONITOR: VMEXIT_CALL_RET(0, hmR0VmxExitMonitor(pVCpu, pVmxTransient));
13267 case VMX_EXIT_TASK_SWITCH: VMEXIT_CALL_RET(0, hmR0VmxExitTaskSwitch(pVCpu, pVmxTransient));
13268 case VMX_EXIT_PREEMPT_TIMER: VMEXIT_CALL_RET(0, hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient));
13269 case VMX_EXIT_RDMSR: VMEXIT_CALL_RET(0, hmR0VmxExitRdmsr(pVCpu, pVmxTransient));
13270 case VMX_EXIT_WRMSR: VMEXIT_CALL_RET(0, hmR0VmxExitWrmsr(pVCpu, pVmxTransient));
13271 case VMX_EXIT_VMCALL: VMEXIT_CALL_RET(0, hmR0VmxExitVmcall(pVCpu, pVmxTransient));
13272 case VMX_EXIT_MOV_DRX: VMEXIT_CALL_RET(0, hmR0VmxExitMovDRx(pVCpu, pVmxTransient));
13273 case VMX_EXIT_HLT: VMEXIT_CALL_RET(0, hmR0VmxExitHlt(pVCpu, pVmxTransient));
13274 case VMX_EXIT_INVD: VMEXIT_CALL_RET(0, hmR0VmxExitInvd(pVCpu, pVmxTransient));
13275 case VMX_EXIT_INVLPG: VMEXIT_CALL_RET(0, hmR0VmxExitInvlpg(pVCpu, pVmxTransient));
13276 case VMX_EXIT_MTF: VMEXIT_CALL_RET(0, hmR0VmxExitMtf(pVCpu, pVmxTransient));
13277 case VMX_EXIT_PAUSE: VMEXIT_CALL_RET(0, hmR0VmxExitPause(pVCpu, pVmxTransient));
13278 case VMX_EXIT_WBINVD: VMEXIT_CALL_RET(0, hmR0VmxExitWbinvd(pVCpu, pVmxTransient));
13279 case VMX_EXIT_XSETBV: VMEXIT_CALL_RET(0, hmR0VmxExitXsetbv(pVCpu, pVmxTransient));
13280 case VMX_EXIT_INVPCID: VMEXIT_CALL_RET(0, hmR0VmxExitInvpcid(pVCpu, pVmxTransient));
13281 case VMX_EXIT_GETSEC: VMEXIT_CALL_RET(0, hmR0VmxExitGetsec(pVCpu, pVmxTransient));
13282 case VMX_EXIT_RDPMC: VMEXIT_CALL_RET(0, hmR0VmxExitRdpmc(pVCpu, pVmxTransient));
13283#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13284 case VMX_EXIT_VMCLEAR: VMEXIT_CALL_RET(0, hmR0VmxExitVmclear(pVCpu, pVmxTransient));
13285 case VMX_EXIT_VMLAUNCH: VMEXIT_CALL_RET(0, hmR0VmxExitVmlaunch(pVCpu, pVmxTransient));
13286 case VMX_EXIT_VMPTRLD: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrld(pVCpu, pVmxTransient));
13287 case VMX_EXIT_VMPTRST: VMEXIT_CALL_RET(0, hmR0VmxExitVmptrst(pVCpu, pVmxTransient));
13288 case VMX_EXIT_VMREAD: VMEXIT_CALL_RET(0, hmR0VmxExitVmread(pVCpu, pVmxTransient));
13289 case VMX_EXIT_VMRESUME: VMEXIT_CALL_RET(0, hmR0VmxExitVmwrite(pVCpu, pVmxTransient));
13290 case VMX_EXIT_VMWRITE: VMEXIT_CALL_RET(0, hmR0VmxExitVmresume(pVCpu, pVmxTransient));
13291 case VMX_EXIT_VMXOFF: VMEXIT_CALL_RET(0, hmR0VmxExitVmxoff(pVCpu, pVmxTransient));
13292 case VMX_EXIT_VMXON: VMEXIT_CALL_RET(0, hmR0VmxExitVmxon(pVCpu, pVmxTransient));
13293 case VMX_EXIT_INVVPID: VMEXIT_CALL_RET(0, hmR0VmxExitInvvpid(pVCpu, pVmxTransient));
13294 case VMX_EXIT_INVEPT: VMEXIT_CALL_RET(0, hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient));
13295#else
13296 case VMX_EXIT_VMCLEAR:
13297 case VMX_EXIT_VMLAUNCH:
13298 case VMX_EXIT_VMPTRLD:
13299 case VMX_EXIT_VMPTRST:
13300 case VMX_EXIT_VMREAD:
13301 case VMX_EXIT_VMRESUME:
13302 case VMX_EXIT_VMWRITE:
13303 case VMX_EXIT_VMXOFF:
13304 case VMX_EXIT_VMXON:
13305 case VMX_EXIT_INVVPID:
13306 case VMX_EXIT_INVEPT:
13307 return hmR0VmxExitSetPendingXcptUD(pVCpu, pVmxTransient);
13308#endif
13309
13310 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFault(pVCpu, pVmxTransient);
13311 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindow(pVCpu, pVmxTransient);
13312 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
13313
13314 case VMX_EXIT_INIT_SIGNAL:
13315 case VMX_EXIT_SIPI:
13316 case VMX_EXIT_IO_SMI:
13317 case VMX_EXIT_SMI:
13318 case VMX_EXIT_ERR_MSR_LOAD:
13319 case VMX_EXIT_ERR_MACHINE_CHECK:
13320 case VMX_EXIT_PML_FULL:
13321 case VMX_EXIT_VIRTUALIZED_EOI:
13322 case VMX_EXIT_GDTR_IDTR_ACCESS:
13323 case VMX_EXIT_LDTR_TR_ACCESS:
13324 case VMX_EXIT_APIC_WRITE:
13325 case VMX_EXIT_RDRAND:
13326 case VMX_EXIT_RSM:
13327 case VMX_EXIT_VMFUNC:
13328 case VMX_EXIT_ENCLS:
13329 case VMX_EXIT_RDSEED:
13330 case VMX_EXIT_XSAVES:
13331 case VMX_EXIT_XRSTORS:
13332 case VMX_EXIT_UMWAIT:
13333 case VMX_EXIT_TPAUSE:
13334 default:
13335 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13336 }
13337#undef VMEXIT_CALL_RET
13338}
13339#endif /* !HMVMX_USE_FUNCTION_TABLE */
13340
13341
13342#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13343/**
13344 * Handles a nested-guest VM-exit from hardware-assisted VMX execution.
13345 *
13346 * @returns Strict VBox status code (i.e. informational status codes too).
13347 * @param pVCpu The cross context virtual CPU structure.
13348 * @param pVmxTransient The VMX-transient structure.
13349 */
13350DECLINLINE(VBOXSTRICTRC) hmR0VmxHandleExitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13351{
13352 uint32_t const uExitReason = pVmxTransient->uExitReason;
13353 switch (uExitReason)
13354 {
13355 case VMX_EXIT_EPT_MISCONFIG: return hmR0VmxExitEptMisconfig(pVCpu, pVmxTransient);
13356 case VMX_EXIT_EPT_VIOLATION: return hmR0VmxExitEptViolation(pVCpu, pVmxTransient);
13357 case VMX_EXIT_XCPT_OR_NMI: return hmR0VmxExitXcptOrNmiNested(pVCpu, pVmxTransient);
13358 case VMX_EXIT_IO_INSTR: return hmR0VmxExitIoInstrNested(pVCpu, pVmxTransient);
13359 case VMX_EXIT_HLT: return hmR0VmxExitHltNested(pVCpu, pVmxTransient);
13360
13361 /*
13362 * We shouldn't direct host physical interrupts to the nested-guest.
13363 */
13364 case VMX_EXIT_EXT_INT:
13365 return hmR0VmxExitExtInt(pVCpu, pVmxTransient);
13366
13367 /*
13368 * Instructions that cause VM-exits unconditionally or the condition is
13369 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13370 * happens, it's guaranteed to be a nested-guest VM-exit).
13371 *
13372 * - Provides VM-exit instruction length ONLY.
13373 */
13374 case VMX_EXIT_CPUID: /* Unconditional. */
13375 case VMX_EXIT_VMCALL:
13376 case VMX_EXIT_GETSEC:
13377 case VMX_EXIT_INVD:
13378 case VMX_EXIT_XSETBV:
13379 case VMX_EXIT_VMLAUNCH:
13380 case VMX_EXIT_VMRESUME:
13381 case VMX_EXIT_VMXOFF:
13382 case VMX_EXIT_ENCLS: /* Condition specified solely by guest hypervisor. */
13383 case VMX_EXIT_VMFUNC:
13384 return hmR0VmxExitInstrNested(pVCpu, pVmxTransient);
13385
13386 /*
13387 * Instructions that cause VM-exits unconditionally or the condition is
13388 * always is taken solely from the guest hypervisor (meaning if the VM-exit
13389 * happens, it's guaranteed to be a nested-guest VM-exit).
13390 *
13391 * - Provides VM-exit instruction length.
13392 * - Provides VM-exit information.
13393 * - Optionally provides Exit qualification.
13394 *
13395 * Since Exit qualification is 0 for all VM-exits where it is not
13396 * applicable, reading and passing it to the guest should produce
13397 * defined behavior.
13398 *
13399 * See Intel spec. 27.2.1 "Basic VM-Exit Information".
13400 */
13401 case VMX_EXIT_INVEPT: /* Unconditional. */
13402 case VMX_EXIT_INVVPID:
13403 case VMX_EXIT_VMCLEAR:
13404 case VMX_EXIT_VMPTRLD:
13405 case VMX_EXIT_VMPTRST:
13406 case VMX_EXIT_VMXON:
13407 case VMX_EXIT_GDTR_IDTR_ACCESS: /* Condition specified solely by guest hypervisor. */
13408 case VMX_EXIT_LDTR_TR_ACCESS:
13409 case VMX_EXIT_RDRAND:
13410 case VMX_EXIT_RDSEED:
13411 case VMX_EXIT_XSAVES:
13412 case VMX_EXIT_XRSTORS:
13413 case VMX_EXIT_UMWAIT:
13414 case VMX_EXIT_TPAUSE:
13415 return hmR0VmxExitInstrWithInfoNested(pVCpu, pVmxTransient);
13416
13417 case VMX_EXIT_RDTSC: return hmR0VmxExitRdtscNested(pVCpu, pVmxTransient);
13418 case VMX_EXIT_RDTSCP: return hmR0VmxExitRdtscpNested(pVCpu, pVmxTransient);
13419 case VMX_EXIT_RDMSR: return hmR0VmxExitRdmsrNested(pVCpu, pVmxTransient);
13420 case VMX_EXIT_WRMSR: return hmR0VmxExitWrmsrNested(pVCpu, pVmxTransient);
13421 case VMX_EXIT_INVLPG: return hmR0VmxExitInvlpgNested(pVCpu, pVmxTransient);
13422 case VMX_EXIT_INVPCID: return hmR0VmxExitInvpcidNested(pVCpu, pVmxTransient);
13423 case VMX_EXIT_TASK_SWITCH: return hmR0VmxExitTaskSwitchNested(pVCpu, pVmxTransient);
13424 case VMX_EXIT_WBINVD: return hmR0VmxExitWbinvdNested(pVCpu, pVmxTransient);
13425 case VMX_EXIT_MTF: return hmR0VmxExitMtfNested(pVCpu, pVmxTransient);
13426 case VMX_EXIT_APIC_ACCESS: return hmR0VmxExitApicAccessNested(pVCpu, pVmxTransient);
13427 case VMX_EXIT_APIC_WRITE: return hmR0VmxExitApicWriteNested(pVCpu, pVmxTransient);
13428 case VMX_EXIT_VIRTUALIZED_EOI: return hmR0VmxExitVirtEoiNested(pVCpu, pVmxTransient);
13429 case VMX_EXIT_MOV_CRX: return hmR0VmxExitMovCRxNested(pVCpu, pVmxTransient);
13430 case VMX_EXIT_INT_WINDOW: return hmR0VmxExitIntWindowNested(pVCpu, pVmxTransient);
13431 case VMX_EXIT_NMI_WINDOW: return hmR0VmxExitNmiWindowNested(pVCpu, pVmxTransient);
13432 case VMX_EXIT_TPR_BELOW_THRESHOLD: return hmR0VmxExitTprBelowThresholdNested(pVCpu, pVmxTransient);
13433 case VMX_EXIT_MWAIT: return hmR0VmxExitMwaitNested(pVCpu, pVmxTransient);
13434 case VMX_EXIT_MONITOR: return hmR0VmxExitMonitorNested(pVCpu, pVmxTransient);
13435 case VMX_EXIT_PAUSE: return hmR0VmxExitPauseNested(pVCpu, pVmxTransient);
13436
13437 case VMX_EXIT_PREEMPT_TIMER:
13438 {
13439 /** @todo NSTVMX: Preempt timer. */
13440 return hmR0VmxExitPreemptTimer(pVCpu, pVmxTransient);
13441 }
13442
13443 case VMX_EXIT_MOV_DRX: return hmR0VmxExitMovDRxNested(pVCpu, pVmxTransient);
13444 case VMX_EXIT_RDPMC: return hmR0VmxExitRdpmcNested(pVCpu, pVmxTransient);
13445
13446 case VMX_EXIT_VMREAD:
13447 case VMX_EXIT_VMWRITE: return hmR0VmxExitVmreadVmwriteNested(pVCpu, pVmxTransient);
13448
13449 case VMX_EXIT_TRIPLE_FAULT: return hmR0VmxExitTripleFaultNested(pVCpu, pVmxTransient);
13450 case VMX_EXIT_ERR_INVALID_GUEST_STATE: return hmR0VmxExitErrInvalidGuestStateNested(pVCpu, pVmxTransient);
13451
13452 case VMX_EXIT_INIT_SIGNAL:
13453 case VMX_EXIT_SIPI:
13454 case VMX_EXIT_IO_SMI:
13455 case VMX_EXIT_SMI:
13456 case VMX_EXIT_ERR_MSR_LOAD:
13457 case VMX_EXIT_ERR_MACHINE_CHECK:
13458 case VMX_EXIT_PML_FULL:
13459 case VMX_EXIT_RSM:
13460 default:
13461 return hmR0VmxExitErrUnexpected(pVCpu, pVmxTransient);
13462 }
13463}
13464#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13465
13466
13467/** @name VM-exit helpers.
13468 * @{
13469 */
13470/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13471/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= VM-exit helpers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
13472/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
13473
13474/** Macro for VM-exits called unexpectedly. */
13475#define HMVMX_UNEXPECTED_EXIT_RET(a_pVCpu, a_HmError) \
13476 do { \
13477 (a_pVCpu)->hm.s.u32HMError = (a_HmError); \
13478 return VERR_VMX_UNEXPECTED_EXIT; \
13479 } while (0)
13480
13481#ifdef VBOX_STRICT
13482/* Is there some generic IPRT define for this that are not in Runtime/internal/\* ?? */
13483# define HMVMX_ASSERT_PREEMPT_CPUID_VAR() \
13484 RTCPUID const idAssertCpu = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId()
13485
13486# define HMVMX_ASSERT_PREEMPT_CPUID() \
13487 do { \
13488 RTCPUID const idAssertCpuNow = RTThreadPreemptIsEnabled(NIL_RTTHREAD) ? NIL_RTCPUID : RTMpCpuId(); \
13489 AssertMsg(idAssertCpu == idAssertCpuNow, ("VMX %#x, %#x\n", idAssertCpu, idAssertCpuNow)); \
13490 } while (0)
13491
13492# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13493 do { \
13494 AssertPtr((a_pVCpu)); \
13495 AssertPtr((a_pVmxTransient)); \
13496 Assert((a_pVmxTransient)->fVMEntryFailed == false); \
13497 Assert((a_pVmxTransient)->pVmcsInfo); \
13498 Assert(ASMIntAreEnabled()); \
13499 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13500 HMVMX_ASSERT_PREEMPT_CPUID_VAR(); \
13501 Log4Func(("vcpu[%RU32]\n", (a_pVCpu)->idCpu)); \
13502 HMVMX_ASSERT_PREEMPT_SAFE(a_pVCpu); \
13503 if (VMMR0IsLogFlushDisabled((a_pVCpu))) \
13504 HMVMX_ASSERT_PREEMPT_CPUID(); \
13505 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13506 } while (0)
13507
13508# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13509 do { \
13510 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); \
13511 Assert((a_pVmxTransient)->fIsNestedGuest); \
13512 } while (0)
13513
13514# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13515 do { \
13516 Log4Func(("\n")); \
13517 } while (0)
13518#else
13519# define HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13520 do { \
13521 HMVMX_STOP_EXIT_DISPATCH_PROF(); \
13522 NOREF((a_pVCpu)); NOREF((a_pVmxTransient)); \
13523 } while (0)
13524
13525# define HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) \
13526 do { HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient); } while (0)
13527
13528# define HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(a_pVCpu, a_pVmxTransient) do { } while (0)
13529#endif
13530
13531#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13532/** Macro that does the necessary privilege checks and intercepted VM-exits for
13533 * guests that attempted to execute a VMX instruction. */
13534# define HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(a_pVCpu, a_uExitReason) \
13535 do \
13536 { \
13537 VBOXSTRICTRC rcStrictTmp = hmR0VmxCheckExitDueToVmxInstr((a_pVCpu), (a_uExitReason)); \
13538 if (rcStrictTmp == VINF_SUCCESS) \
13539 { /* likely */ } \
13540 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13541 { \
13542 Assert((a_pVCpu)->hm.s.Event.fPending); \
13543 Log4Func(("Privilege checks failed -> %#x\n", VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo))); \
13544 return VINF_SUCCESS; \
13545 } \
13546 else \
13547 { \
13548 int rcTmp = VBOXSTRICTRC_VAL(rcStrictTmp); \
13549 AssertMsgFailedReturn(("Unexpected failure. rc=%Rrc", rcTmp), rcTmp); \
13550 } \
13551 } while (0)
13552
13553/** Macro that decodes a memory operand for an VM-exit caused by an instruction. */
13554# define HMVMX_DECODE_MEM_OPERAND(a_pVCpu, a_uExitInstrInfo, a_uExitQual, a_enmMemAccess, a_pGCPtrEffAddr) \
13555 do \
13556 { \
13557 VBOXSTRICTRC rcStrictTmp = hmR0VmxDecodeMemOperand((a_pVCpu), (a_uExitInstrInfo), (a_uExitQual), (a_enmMemAccess), \
13558 (a_pGCPtrEffAddr)); \
13559 if (rcStrictTmp == VINF_SUCCESS) \
13560 { /* likely */ } \
13561 else if (rcStrictTmp == VINF_HM_PENDING_XCPT) \
13562 { \
13563 uint8_t const uXcptTmp = VMX_ENTRY_INT_INFO_VECTOR((a_pVCpu)->hm.s.Event.u64IntInfo); \
13564 Log4Func(("Memory operand decoding failed, raising xcpt %#x\n", uXcptTmp)); \
13565 NOREF(uXcptTmp); \
13566 return VINF_SUCCESS; \
13567 } \
13568 else \
13569 { \
13570 Log4Func(("hmR0VmxDecodeMemOperand failed. rc=%Rrc\n", VBOXSTRICTRC_VAL(rcStrictTmp))); \
13571 return rcStrictTmp; \
13572 } \
13573 } while (0)
13574#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
13575
13576
13577/**
13578 * Advances the guest RIP by the specified number of bytes.
13579 *
13580 * @param pVCpu The cross context virtual CPU structure.
13581 * @param cbInstr Number of bytes to advance the RIP by.
13582 *
13583 * @remarks No-long-jump zone!!!
13584 */
13585DECLINLINE(void) hmR0VmxAdvanceGuestRipBy(PVMCPU pVCpu, uint32_t cbInstr)
13586{
13587 /* Advance the RIP. */
13588 pVCpu->cpum.GstCtx.rip += cbInstr;
13589 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
13590
13591 /* Update interrupt inhibition. */
13592 if ( VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS)
13593 && pVCpu->cpum.GstCtx.rip != EMGetInhibitInterruptsPC(pVCpu))
13594 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
13595}
13596
13597
13598/**
13599 * Advances the guest RIP after reading it from the VMCS.
13600 *
13601 * @returns VBox status code, no informational status codes.
13602 * @param pVCpu The cross context virtual CPU structure.
13603 * @param pVmxTransient The VMX-transient structure.
13604 *
13605 * @remarks No-long-jump zone!!!
13606 */
13607static int hmR0VmxAdvanceGuestRip(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13608{
13609 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13610 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS);
13611 AssertRCReturn(rc, rc);
13612
13613 hmR0VmxAdvanceGuestRipBy(pVCpu, pVmxTransient->cbInstr);
13614 return VINF_SUCCESS;
13615}
13616
13617
13618#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13619/**
13620 * Handle a condition that occurred while delivering an event through the
13621 * nested-guest IDT.
13622 *
13623 * @returns VBox status code.
13624 * @param pVCpu The cross context virtual CPU structure.
13625 * @param pVmxTransient The VMX-transient structure.
13626 *
13627 * @remarks No-long-jump zone!!!
13628 */
13629static int hmR0VmxCheckExitDueToEventDeliveryNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13630{
13631 Assert(pVmxTransient->fIsNestedGuest);
13632 Assert(!pVCpu->hm.s.Event.fPending);
13633
13634#ifdef VBOX_STRICT
13635 /*
13636 * Validate we have read the required fields from the VMCS.
13637 */
13638 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
13639 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
13640 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
13641#endif
13642
13643 /*
13644 * Construct a pending event from IDT vectoring information.
13645 *
13646 * This event could have originated from an event that we or the guest hypervisor injected
13647 * during nested-guest VM-entry or could arise from hardware-assisted VMX execution of the
13648 * nested-guest (for e.g. a #GP fault causing a #PF VM-exit).
13649 *
13650 * If the VM-exit is caused indirectly due to delivery of:
13651 * - #PF: the CPU would have updated CR2.
13652 * - NMI: NMI/virtual-NMI blocking is in effect.
13653 *
13654 * The main differences between this function and its non-nested version are as follows:
13655 *
13656 * - Here we record software interrupts, software exceptions and privileged software
13657 * exceptions as pending for re-injection when necessary along with gathering the
13658 * instruction length. The non-nested version would fix-up the VM-exit that occurred
13659 * during delivery of such an event and restart execution of the guest without
13660 * re-injecting the event and does not record the instruction length.
13661 *
13662 * - Here we record #PF as pending for re-injection while the non-nested version would
13663 * handle it via the page-fault VM-exit handler which isn't required when nested paging
13664 * is a requirement for hardware-assisted VMX execution of nested-guests.
13665 *
13666 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
13667 */
13668 int rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
13669 AssertRCReturn(rc, rc);
13670
13671 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13672 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13673 {
13674 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13675 uint8_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13676
13677 /*
13678 * Get the nasty stuff out of the way.
13679 */
13680 {
13681 rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
13682 AssertRCReturn(rc, rc);
13683
13684 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13685 if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13686 {
13687 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
13688 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13689 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13690
13691 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13692 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13693
13694 IEMXCPTRAISEINFO fRaiseInfo;
13695 IEMXCPTRAISE const enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags,
13696 uExitVector, &fRaiseInfo);
13697 if (enmRaise == IEMXCPTRAISE_CPU_HANG)
13698 {
13699 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13700 return VERR_EM_GUEST_CPU_HANG;
13701 }
13702 }
13703 }
13704
13705 /*
13706 * Things look legit, continue...
13707 */
13708 uint32_t u32ErrCode;
13709 bool const fErrCodeValid = VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo);
13710 if (fErrCodeValid)
13711 {
13712 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
13713 AssertRCReturn(rc, rc);
13714 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13715 }
13716 else
13717 u32ErrCode = 0;
13718
13719 uint32_t cbInstr;
13720 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13721 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT
13722 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT)
13723 {
13724 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
13725 AssertRCReturn(rc, rc);
13726 cbInstr = pVmxTransient->cbInstr;
13727 }
13728 else
13729 cbInstr = 0;
13730
13731 RTGCUINTPTR GCPtrFaultAddress;
13732 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(uIdtVectorInfo))
13733 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
13734 else
13735 GCPtrFaultAddress = 0;
13736
13737 if (VMX_IDT_VECTORING_INFO_IS_XCPT_NMI(uIdtVectorInfo))
13738 CPUMSetGuestNmiBlocking(pVCpu, true);
13739
13740 hmR0VmxSetPendingEvent(pVCpu, uIdtVectorInfo, cbInstr, u32ErrCode, GCPtrFaultAddress);
13741 }
13742
13743 return VINF_SUCCESS;
13744}
13745#endif
13746
13747
13748/**
13749 * Handle a condition that occurred while delivering an event through the guest or
13750 * nested-guest IDT.
13751 *
13752 * @returns Strict VBox status code (i.e. informational status codes too).
13753 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13754 * @retval VINF_HM_DOUBLE_FAULT if a \#DF condition was detected and we ought
13755 * to continue execution of the guest which will delivery the \#DF.
13756 * @retval VINF_EM_RESET if we detected a triple-fault condition.
13757 * @retval VERR_EM_GUEST_CPU_HANG if we detected a guest CPU hang.
13758 *
13759 * @param pVCpu The cross context virtual CPU structure.
13760 * @param pVmxTransient The VMX-transient structure.
13761 *
13762 * @remarks No-long-jump zone!!!
13763 */
13764static VBOXSTRICTRC hmR0VmxCheckExitDueToEventDelivery(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
13765{
13766#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13767 if (pVmxTransient->fIsNestedGuest)
13768 return hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
13769#endif
13770
13771 Assert(!pVmxTransient->fIsNestedGuest);
13772 VBOXSTRICTRC rcStrict = VINF_SUCCESS;
13773
13774#ifdef VBOX_STRICT
13775 /*
13776 * Validate we have read the required fields from the VMCS.
13777 */
13778 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
13779 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
13780 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
13781#endif
13782
13783 uint32_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
13784 uint8_t const uExitVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
13785 uint32_t const uIdtVectorInfo = pVmxTransient->uIdtVectoringInfo;
13786 if (VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo))
13787 {
13788 uint32_t const uIdtVector = VMX_IDT_VECTORING_INFO_VECTOR(uIdtVectorInfo);
13789 uint32_t const uIdtVectorType = VMX_IDT_VECTORING_INFO_TYPE(uIdtVectorInfo);
13790
13791 /*
13792 * If the event was a software interrupt (generated with INT n) or a software exception
13793 * (generated by INT3/INTO) or a privileged software exception (generated by INT1), we
13794 * can handle the VM-exit and continue guest execution which will re-execute the
13795 * instruction rather than re-injecting the exception, as that can cause premature
13796 * trips to ring-3 before injection and involve TRPM which currently has no way of
13797 * storing that these exceptions were caused by these instructions (ICEBP's #DB poses
13798 * the problem).
13799 */
13800 IEMXCPTRAISE enmRaise;
13801 IEMXCPTRAISEINFO fRaiseInfo;
13802 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
13803 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT
13804 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT)
13805 {
13806 enmRaise = IEMXCPTRAISE_REEXEC_INSTR;
13807 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13808 }
13809 else if (VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo))
13810 {
13811 uint32_t const uExitVectorType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
13812 Assert(uExitVectorType == VMX_EXIT_INT_INFO_TYPE_HW_XCPT);
13813
13814 uint32_t const fIdtVectorFlags = hmR0VmxGetIemXcptFlags(uIdtVector, uIdtVectorType);
13815 uint32_t const fExitVectorFlags = hmR0VmxGetIemXcptFlags(uExitVector, uExitVectorType);
13816
13817 enmRaise = IEMEvaluateRecursiveXcpt(pVCpu, fIdtVectorFlags, uIdtVector, fExitVectorFlags, uExitVector, &fRaiseInfo);
13818
13819 /* Determine a vectoring #PF condition, see comment in hmR0VmxExitXcptPF(). */
13820 if (fRaiseInfo & (IEMXCPTRAISEINFO_EXT_INT_PF | IEMXCPTRAISEINFO_NMI_PF))
13821 {
13822 pVmxTransient->fVectoringPF = true;
13823 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13824 }
13825 }
13826 else
13827 {
13828 /*
13829 * If an exception or hardware interrupt delivery caused an EPT violation/misconfig or APIC access
13830 * VM-exit, then the VM-exit interruption-information will not be valid and we end up here.
13831 * It is sufficient to reflect the original event to the guest after handling the VM-exit.
13832 */
13833 Assert( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_HW_XCPT
13834 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13835 || uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_EXT_INT);
13836 enmRaise = IEMXCPTRAISE_PREV_EVENT;
13837 fRaiseInfo = IEMXCPTRAISEINFO_NONE;
13838 }
13839
13840 /*
13841 * On CPUs that support Virtual NMIs, if this VM-exit (be it an exception or EPT violation/misconfig
13842 * etc.) occurred while delivering the NMI, we need to clear the block-by-NMI field in the guest
13843 * interruptibility-state before re-delivering the NMI after handling the VM-exit. Otherwise the
13844 * subsequent VM-entry would fail, see @bugref{7445}.
13845 *
13846 * See Intel spec. 30.7.1.2 "Resuming Guest Software after Handling an Exception".
13847 */
13848 if ( uIdtVectorType == VMX_IDT_VECTORING_INFO_TYPE_NMI
13849 && ( enmRaise == IEMXCPTRAISE_PREV_EVENT
13850 || (fRaiseInfo & IEMXCPTRAISEINFO_NMI_PF))
13851 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI)
13852 && CPUMIsGuestNmiBlocking(pVCpu))
13853 {
13854 CPUMSetGuestNmiBlocking(pVCpu, false);
13855 }
13856
13857 switch (enmRaise)
13858 {
13859 case IEMXCPTRAISE_CURRENT_XCPT:
13860 {
13861 Log4Func(("IDT: Pending secondary Xcpt: uIdtVectoringInfo=%#RX64 uExitIntInfo=%#RX64\n", uIdtVectorInfo,
13862 uExitIntInfo));
13863 Assert(rcStrict == VINF_SUCCESS);
13864 break;
13865 }
13866
13867 case IEMXCPTRAISE_PREV_EVENT:
13868 {
13869 uint32_t u32ErrCode;
13870 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(uIdtVectorInfo))
13871 u32ErrCode = pVmxTransient->uIdtVectoringErrorCode;
13872 else
13873 u32ErrCode = 0;
13874
13875 /* If uExitVector is #PF, CR2 value will be updated from the VMCS if it's a guest #PF, see hmR0VmxExitXcptPF(). */
13876 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflect);
13877 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(uIdtVectorInfo), 0 /* cbInstr */,
13878 u32ErrCode, pVCpu->cpum.GstCtx.cr2);
13879
13880 Log4Func(("IDT: Pending vectoring event %#RX64 Err=%#RX32\n", pVCpu->hm.s.Event.u64IntInfo,
13881 pVCpu->hm.s.Event.u32ErrCode));
13882 Assert(rcStrict == VINF_SUCCESS);
13883 break;
13884 }
13885
13886 case IEMXCPTRAISE_REEXEC_INSTR:
13887 Assert(rcStrict == VINF_SUCCESS);
13888 break;
13889
13890 case IEMXCPTRAISE_DOUBLE_FAULT:
13891 {
13892 /*
13893 * Determing a vectoring double #PF condition. Used later, when PGM evaluates the
13894 * second #PF as a guest #PF (and not a shadow #PF) and needs to be converted into a #DF.
13895 */
13896 if (fRaiseInfo & IEMXCPTRAISEINFO_PF_PF)
13897 {
13898 pVmxTransient->fVectoringDoublePF = true;
13899 Log4Func(("IDT: Vectoring double #PF %#RX64 cr2=%#RX64\n", pVCpu->hm.s.Event.u64IntInfo,
13900 pVCpu->cpum.GstCtx.cr2));
13901 rcStrict = VINF_SUCCESS;
13902 }
13903 else
13904 {
13905 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectConvertDF);
13906 hmR0VmxSetPendingXcptDF(pVCpu);
13907 Log4Func(("IDT: Pending vectoring #DF %#RX64 uIdtVector=%#x uExitVector=%#x\n", pVCpu->hm.s.Event.u64IntInfo,
13908 uIdtVector, uExitVector));
13909 rcStrict = VINF_HM_DOUBLE_FAULT;
13910 }
13911 break;
13912 }
13913
13914 case IEMXCPTRAISE_TRIPLE_FAULT:
13915 {
13916 Log4Func(("IDT: Pending vectoring triple-fault uIdt=%#x uExit=%#x\n", uIdtVector, uExitVector));
13917 rcStrict = VINF_EM_RESET;
13918 break;
13919 }
13920
13921 case IEMXCPTRAISE_CPU_HANG:
13922 {
13923 Log4Func(("IDT: Bad guest! Entering CPU hang. fRaiseInfo=%#x\n", fRaiseInfo));
13924 rcStrict = VERR_EM_GUEST_CPU_HANG;
13925 break;
13926 }
13927
13928 default:
13929 {
13930 AssertMsgFailed(("IDT: vcpu[%RU32] Unexpected/invalid value! enmRaise=%#x\n", pVCpu->idCpu, enmRaise));
13931 rcStrict = VERR_VMX_IPE_2;
13932 break;
13933 }
13934 }
13935 }
13936 else if ( VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo)
13937 && VMX_EXIT_INT_INFO_IS_NMI_UNBLOCK_IRET(uExitIntInfo)
13938 && uExitVector != X86_XCPT_DF
13939 && hmR0VmxIsPinCtlsSet(pVCpu, pVmxTransient, VMX_PIN_CTLS_VIRT_NMI))
13940 {
13941 Assert(!VMX_IDT_VECTORING_INFO_IS_VALID(uIdtVectorInfo));
13942
13943 /*
13944 * Execution of IRET caused this fault when NMI blocking was in effect (i.e we're in the guest NMI handler).
13945 * We need to set the block-by-NMI field so that NMIs remain blocked until the IRET execution is restarted.
13946 * See Intel spec. 30.7.1.2 "Resuming guest software after handling an exception".
13947 */
13948 CPUMSetGuestNmiBlocking(pVCpu, true);
13949 Log4Func(("Set NMI blocking. uExitReason=%u\n", pVmxTransient->uExitReason));
13950 }
13951
13952 Assert( rcStrict == VINF_SUCCESS || rcStrict == VINF_HM_DOUBLE_FAULT
13953 || rcStrict == VINF_EM_RESET || rcStrict == VERR_EM_GUEST_CPU_HANG);
13954 return rcStrict;
13955}
13956
13957
13958#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
13959/**
13960 * Perform the relevant VMX instruction checks for VM-exits that occurred due to the
13961 * guest attempting to execute a VMX instruction.
13962 *
13963 * @returns Strict VBox status code (i.e. informational status codes too).
13964 * @retval VINF_SUCCESS if we should continue handling the VM-exit.
13965 * @retval VINF_HM_PENDING_XCPT if an exception was raised.
13966 *
13967 * @param pVCpu The cross context virtual CPU structure.
13968 * @param uExitReason The VM-exit reason.
13969 *
13970 * @todo NSTVMX: Document other error codes when VM-exit is implemented.
13971 * @remarks No-long-jump zone!!!
13972 */
13973static VBOXSTRICTRC hmR0VmxCheckExitDueToVmxInstr(PVMCPU pVCpu, uint32_t uExitReason)
13974{
13975 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS
13976 | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
13977
13978 /*
13979 * The physical CPU would have already checked the CPU mode/code segment.
13980 * We shall just assert here for paranoia.
13981 * See Intel spec. 25.1.1 "Relative Priority of Faults and VM Exits".
13982 */
13983 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
13984 Assert( !CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx)
13985 || CPUMIsGuestIn64BitCodeEx(&pVCpu->cpum.GstCtx));
13986
13987 if (uExitReason == VMX_EXIT_VMXON)
13988 {
13989 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR4);
13990
13991 /*
13992 * We check CR4.VMXE because it is required to be always set while in VMX operation
13993 * by physical CPUs and our CR4 read-shadow is only consulted when executing specific
13994 * instructions (CLTS, LMSW, MOV CR, and SMSW) and thus doesn't affect CPU operation
13995 * otherwise (i.e. physical CPU won't automatically #UD if Cr4Shadow.VMXE is 0).
13996 */
13997 if (!CPUMIsGuestVmxEnabled(&pVCpu->cpum.GstCtx))
13998 {
13999 Log4Func(("CR4.VMXE is not set -> #UD\n"));
14000 hmR0VmxSetPendingXcptUD(pVCpu);
14001 return VINF_HM_PENDING_XCPT;
14002 }
14003 }
14004 else if (!CPUMIsGuestInVmxRootMode(&pVCpu->cpum.GstCtx))
14005 {
14006 /*
14007 * The guest has not entered VMX operation but attempted to execute a VMX instruction
14008 * (other than VMXON), we need to raise a #UD.
14009 */
14010 Log4Func(("Not in VMX root mode -> #UD\n"));
14011 hmR0VmxSetPendingXcptUD(pVCpu);
14012 return VINF_HM_PENDING_XCPT;
14013 }
14014
14015 /* All other checks (including VM-exit intercepts) are handled by IEM instruction emulation. */
14016 return VINF_SUCCESS;
14017}
14018
14019/**
14020 * Decodes the memory operand of an instruction that caused a VM-exit.
14021 *
14022 * The Exit qualification field provides the displacement field for memory
14023 * operand instructions, if any.
14024 *
14025 * @returns Strict VBox status code (i.e. informational status codes too).
14026 * @retval VINF_SUCCESS if the operand was successfully decoded.
14027 * @retval VINF_HM_PENDING_XCPT if an exception was raised while decoding the
14028 * operand.
14029 * @param pVCpu The cross context virtual CPU structure.
14030 * @param uExitInstrInfo The VM-exit instruction information field.
14031 * @param enmMemAccess The memory operand's access type (read or write).
14032 * @param GCPtrDisp The instruction displacement field, if any. For
14033 * RIP-relative addressing pass RIP + displacement here.
14034 * @param pGCPtrMem Where to store the effective destination memory address.
14035 *
14036 * @remarks Warning! This function ASSUMES the instruction cannot be used in real or
14037 * virtual-8086 mode hence skips those checks while verifying if the
14038 * segment is valid.
14039 */
14040static VBOXSTRICTRC hmR0VmxDecodeMemOperand(PVMCPU pVCpu, uint32_t uExitInstrInfo, RTGCPTR GCPtrDisp, VMXMEMACCESS enmMemAccess,
14041 PRTGCPTR pGCPtrMem)
14042{
14043 Assert(pGCPtrMem);
14044 Assert(!CPUMIsGuestInRealOrV86Mode(pVCpu));
14045 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_EFER
14046 | CPUMCTX_EXTRN_CR0);
14047
14048 static uint64_t const s_auAddrSizeMasks[] = { UINT64_C(0xffff), UINT64_C(0xffffffff), UINT64_C(0xffffffffffffffff) };
14049 static uint64_t const s_auAccessSizeMasks[] = { sizeof(uint16_t), sizeof(uint32_t), sizeof(uint64_t) };
14050 AssertCompile(RT_ELEMENTS(s_auAccessSizeMasks) == RT_ELEMENTS(s_auAddrSizeMasks));
14051
14052 VMXEXITINSTRINFO ExitInstrInfo;
14053 ExitInstrInfo.u = uExitInstrInfo;
14054 uint8_t const uAddrSize = ExitInstrInfo.All.u3AddrSize;
14055 uint8_t const iSegReg = ExitInstrInfo.All.iSegReg;
14056 bool const fIdxRegValid = !ExitInstrInfo.All.fIdxRegInvalid;
14057 uint8_t const iIdxReg = ExitInstrInfo.All.iIdxReg;
14058 uint8_t const uScale = ExitInstrInfo.All.u2Scaling;
14059 bool const fBaseRegValid = !ExitInstrInfo.All.fBaseRegInvalid;
14060 uint8_t const iBaseReg = ExitInstrInfo.All.iBaseReg;
14061 bool const fIsMemOperand = !ExitInstrInfo.All.fIsRegOperand;
14062 bool const fIsLongMode = CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx);
14063
14064 /*
14065 * Validate instruction information.
14066 * This shouldn't happen on real hardware but useful while testing our nested hardware-virtualization code.
14067 */
14068 AssertLogRelMsgReturn(uAddrSize < RT_ELEMENTS(s_auAddrSizeMasks),
14069 ("Invalid address size. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_1);
14070 AssertLogRelMsgReturn(iSegReg < X86_SREG_COUNT,
14071 ("Invalid segment register. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_2);
14072 AssertLogRelMsgReturn(fIsMemOperand,
14073 ("Expected memory operand. ExitInstrInfo=%#RX32\n", ExitInstrInfo.u), VERR_VMX_IPE_3);
14074
14075 /*
14076 * Compute the complete effective address.
14077 *
14078 * See AMD instruction spec. 1.4.2 "SIB Byte Format"
14079 * See AMD spec. 4.5.2 "Segment Registers".
14080 */
14081 RTGCPTR GCPtrMem = GCPtrDisp;
14082 if (fBaseRegValid)
14083 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iBaseReg].u64;
14084 if (fIdxRegValid)
14085 GCPtrMem += pVCpu->cpum.GstCtx.aGRegs[iIdxReg].u64 << uScale;
14086
14087 RTGCPTR const GCPtrOff = GCPtrMem;
14088 if ( !fIsLongMode
14089 || iSegReg >= X86_SREG_FS)
14090 GCPtrMem += pVCpu->cpum.GstCtx.aSRegs[iSegReg].u64Base;
14091 GCPtrMem &= s_auAddrSizeMasks[uAddrSize];
14092
14093 /*
14094 * Validate effective address.
14095 * See AMD spec. 4.5.3 "Segment Registers in 64-Bit Mode".
14096 */
14097 uint8_t const cbAccess = s_auAccessSizeMasks[uAddrSize];
14098 Assert(cbAccess > 0);
14099 if (fIsLongMode)
14100 {
14101 if (X86_IS_CANONICAL(GCPtrMem))
14102 {
14103 *pGCPtrMem = GCPtrMem;
14104 return VINF_SUCCESS;
14105 }
14106
14107 /** @todo r=ramshankar: We should probably raise \#SS or \#GP. See AMD spec. 4.12.2
14108 * "Data Limit Checks in 64-bit Mode". */
14109 Log4Func(("Long mode effective address is not canonical GCPtrMem=%#RX64\n", GCPtrMem));
14110 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14111 return VINF_HM_PENDING_XCPT;
14112 }
14113
14114 /*
14115 * This is a watered down version of iemMemApplySegment().
14116 * Parts that are not applicable for VMX instructions like real-or-v8086 mode
14117 * and segment CPL/DPL checks are skipped.
14118 */
14119 RTGCPTR32 const GCPtrFirst32 = (RTGCPTR32)GCPtrOff;
14120 RTGCPTR32 const GCPtrLast32 = GCPtrFirst32 + cbAccess - 1;
14121 PCCPUMSELREG pSel = &pVCpu->cpum.GstCtx.aSRegs[iSegReg];
14122
14123 /* Check if the segment is present and usable. */
14124 if ( pSel->Attr.n.u1Present
14125 && !pSel->Attr.n.u1Unusable)
14126 {
14127 Assert(pSel->Attr.n.u1DescType);
14128 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_CODE))
14129 {
14130 /* Check permissions for the data segment. */
14131 if ( enmMemAccess == VMXMEMACCESS_WRITE
14132 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_WRITE))
14133 {
14134 Log4Func(("Data segment access invalid. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14135 hmR0VmxSetPendingXcptGP(pVCpu, iSegReg);
14136 return VINF_HM_PENDING_XCPT;
14137 }
14138
14139 /* Check limits if it's a normal data segment. */
14140 if (!(pSel->Attr.n.u4Type & X86_SEL_TYPE_DOWN))
14141 {
14142 if ( GCPtrFirst32 > pSel->u32Limit
14143 || GCPtrLast32 > pSel->u32Limit)
14144 {
14145 Log4Func(("Data segment limit exceeded. "
14146 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14147 GCPtrLast32, pSel->u32Limit));
14148 if (iSegReg == X86_SREG_SS)
14149 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14150 else
14151 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14152 return VINF_HM_PENDING_XCPT;
14153 }
14154 }
14155 else
14156 {
14157 /* Check limits if it's an expand-down data segment.
14158 Note! The upper boundary is defined by the B bit, not the G bit! */
14159 if ( GCPtrFirst32 < pSel->u32Limit + UINT32_C(1)
14160 || GCPtrLast32 > (pSel->Attr.n.u1DefBig ? UINT32_MAX : UINT32_C(0xffff)))
14161 {
14162 Log4Func(("Expand-down data segment limit exceeded. "
14163 "iSegReg=%#x GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n", iSegReg, GCPtrFirst32,
14164 GCPtrLast32, pSel->u32Limit));
14165 if (iSegReg == X86_SREG_SS)
14166 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14167 else
14168 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14169 return VINF_HM_PENDING_XCPT;
14170 }
14171 }
14172 }
14173 else
14174 {
14175 /* Check permissions for the code segment. */
14176 if ( enmMemAccess == VMXMEMACCESS_WRITE
14177 || ( enmMemAccess == VMXMEMACCESS_READ
14178 && !(pSel->Attr.n.u4Type & X86_SEL_TYPE_READ)))
14179 {
14180 Log4Func(("Code segment access invalid. Attr=%#RX32\n", pSel->Attr.u));
14181 Assert(!CPUMIsGuestInRealOrV86ModeEx(&pVCpu->cpum.GstCtx));
14182 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14183 return VINF_HM_PENDING_XCPT;
14184 }
14185
14186 /* Check limits for the code segment (normal/expand-down not applicable for code segments). */
14187 if ( GCPtrFirst32 > pSel->u32Limit
14188 || GCPtrLast32 > pSel->u32Limit)
14189 {
14190 Log4Func(("Code segment limit exceeded. GCPtrFirst32=%#RX32 GCPtrLast32=%#RX32 u32Limit=%#RX32\n",
14191 GCPtrFirst32, GCPtrLast32, pSel->u32Limit));
14192 if (iSegReg == X86_SREG_SS)
14193 hmR0VmxSetPendingXcptSS(pVCpu, 0);
14194 else
14195 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14196 return VINF_HM_PENDING_XCPT;
14197 }
14198 }
14199 }
14200 else
14201 {
14202 Log4Func(("Not present or unusable segment. iSegReg=%#x Attr=%#RX32\n", iSegReg, pSel->Attr.u));
14203 hmR0VmxSetPendingXcptGP(pVCpu, 0);
14204 return VINF_HM_PENDING_XCPT;
14205 }
14206
14207 *pGCPtrMem = GCPtrMem;
14208 return VINF_SUCCESS;
14209}
14210#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
14211
14212
14213/**
14214 * VM-exit helper for LMSW.
14215 */
14216static VBOXSTRICTRC hmR0VmxExitLmsw(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint16_t uMsw, RTGCPTR GCPtrEffDst)
14217{
14218 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14219 AssertRCReturn(rc, rc);
14220
14221 VBOXSTRICTRC rcStrict = IEMExecDecodedLmsw(pVCpu, cbInstr, uMsw, GCPtrEffDst);
14222 AssertMsg( rcStrict == VINF_SUCCESS
14223 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14224
14225 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14226 if (rcStrict == VINF_IEM_RAISED_XCPT)
14227 {
14228 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14229 rcStrict = VINF_SUCCESS;
14230 }
14231
14232 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitLmsw);
14233 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14234 return rcStrict;
14235}
14236
14237
14238/**
14239 * VM-exit helper for CLTS.
14240 */
14241static VBOXSTRICTRC hmR0VmxExitClts(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr)
14242{
14243 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14244 AssertRCReturn(rc, rc);
14245
14246 VBOXSTRICTRC rcStrict = IEMExecDecodedClts(pVCpu, cbInstr);
14247 AssertMsg( rcStrict == VINF_SUCCESS
14248 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14249
14250 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14251 if (rcStrict == VINF_IEM_RAISED_XCPT)
14252 {
14253 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14254 rcStrict = VINF_SUCCESS;
14255 }
14256
14257 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitClts);
14258 Log4Func(("rcStrict=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14259 return rcStrict;
14260}
14261
14262
14263/**
14264 * VM-exit helper for MOV from CRx (CRx read).
14265 */
14266static VBOXSTRICTRC hmR0VmxExitMovFromCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14267{
14268 Assert(iCrReg < 16);
14269 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
14270
14271 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14272 AssertRCReturn(rc, rc);
14273
14274 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxRead(pVCpu, cbInstr, iGReg, iCrReg);
14275 AssertMsg( rcStrict == VINF_SUCCESS
14276 || rcStrict == VINF_IEM_RAISED_XCPT, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14277
14278 if (iGReg == X86_GREG_xSP)
14279 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_RSP);
14280 else
14281 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
14282#ifdef VBOX_WITH_STATISTICS
14283 switch (iCrReg)
14284 {
14285 case 0: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Read); break;
14286 case 2: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Read); break;
14287 case 3: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Read); break;
14288 case 4: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Read); break;
14289 case 8: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Read); break;
14290 }
14291#endif
14292 Log4Func(("CR%d Read access rcStrict=%Rrc\n", iCrReg, VBOXSTRICTRC_VAL(rcStrict)));
14293 return rcStrict;
14294}
14295
14296
14297/**
14298 * VM-exit helper for MOV to CRx (CRx write).
14299 */
14300static VBOXSTRICTRC hmR0VmxExitMovToCrX(PVMCPU pVCpu, PVMXVMCSINFO pVmcsInfo, uint8_t cbInstr, uint8_t iGReg, uint8_t iCrReg)
14301{
14302 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
14303 AssertRCReturn(rc, rc);
14304
14305 VBOXSTRICTRC rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, cbInstr, iCrReg, iGReg);
14306 AssertMsg( rcStrict == VINF_SUCCESS
14307 || rcStrict == VINF_IEM_RAISED_XCPT
14308 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
14309
14310 switch (iCrReg)
14311 {
14312 case 0:
14313 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR0);
14314 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
14315 Log4Func(("CR0 write. rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
14316 break;
14317
14318 case 2:
14319 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR2Write);
14320 /* Nothing to do here, CR2 it's not part of the VMCS. */
14321 break;
14322
14323 case 3:
14324 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR3);
14325 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR3Write);
14326 Log4Func(("CR3 write. rcStrict=%Rrc CR3=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr3));
14327 break;
14328
14329 case 4:
14330 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_CR4);
14331 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR4Write);
14332 Log4Func(("CR4 write. rc=%Rrc CR4=%#RX64 fLoadSaveGuestXcr0=%u\n", VBOXSTRICTRC_VAL(rcStrict),
14333 pVCpu->cpum.GstCtx.cr4, pVCpu->hm.s.fLoadSaveGuestXcr0));
14334 break;
14335
14336 case 8:
14337 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged,
14338 HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_APIC_TPR);
14339 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR8Write);
14340 break;
14341
14342 default:
14343 AssertMsgFailed(("Invalid CRx register %#x\n", iCrReg));
14344 break;
14345 }
14346
14347 if (rcStrict == VINF_IEM_RAISED_XCPT)
14348 {
14349 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14350 rcStrict = VINF_SUCCESS;
14351 }
14352 return rcStrict;
14353}
14354
14355
14356/**
14357 * VM-exit exception handler for \#PF (Page-fault exception).
14358 *
14359 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14360 */
14361static VBOXSTRICTRC hmR0VmxExitXcptPF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14362{
14363 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14364 PVM pVM = pVCpu->CTX_SUFF(pVM);
14365 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14366 AssertRCReturn(rc, rc);
14367
14368 if (!pVM->hm.s.fNestedPaging)
14369 { /* likely */ }
14370 else
14371 {
14372#if !defined(HMVMX_ALWAYS_TRAP_ALL_XCPTS) && !defined(HMVMX_ALWAYS_TRAP_PF)
14373 Assert(pVmxTransient->fIsNestedGuest || pVCpu->hm.s.fUsingDebugLoop);
14374#endif
14375 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory or vectoring #PF. */
14376 if (!pVmxTransient->fVectoringDoublePF)
14377 {
14378 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14379 pVmxTransient->uExitIntErrorCode, pVmxTransient->uExitQual);
14380 }
14381 else
14382 {
14383 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14384 Assert(!pVmxTransient->fIsNestedGuest);
14385 hmR0VmxSetPendingXcptDF(pVCpu);
14386 Log4Func(("Pending #DF due to vectoring #PF w/ NestedPaging\n"));
14387 }
14388 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14389 return rc;
14390 }
14391
14392 Assert(!pVmxTransient->fIsNestedGuest);
14393
14394 /* If it's a vectoring #PF, emulate injecting the original event injection as PGMTrap0eHandler() is incapable
14395 of differentiating between instruction emulation and event injection that caused a #PF. See @bugref{6607}. */
14396 if (pVmxTransient->fVectoringPF)
14397 {
14398 Assert(pVCpu->hm.s.Event.fPending);
14399 return VINF_EM_RAW_INJECT_TRPM_EVENT;
14400 }
14401
14402 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14403 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14404 AssertRCReturn(rc, rc);
14405
14406 Log4Func(("#PF: cr2=%#RX64 cs:rip=%#04x:%#RX64 uErrCode %#RX32 cr3=%#RX64\n", pVmxTransient->uExitQual, pCtx->cs.Sel,
14407 pCtx->rip, pVmxTransient->uExitIntErrorCode, pCtx->cr3));
14408
14409 TRPMAssertXcptPF(pVCpu, pVmxTransient->uExitQual, (RTGCUINT)pVmxTransient->uExitIntErrorCode);
14410 rc = PGMTrap0eHandler(pVCpu, pVmxTransient->uExitIntErrorCode, CPUMCTX2CORE(pCtx), (RTGCPTR)pVmxTransient->uExitQual);
14411
14412 Log4Func(("#PF: rc=%Rrc\n", rc));
14413 if (rc == VINF_SUCCESS)
14414 {
14415 /*
14416 * This is typically a shadow page table sync or a MMIO instruction. But we may have
14417 * emulated something like LTR or a far jump. Any part of the CPU context may have changed.
14418 */
14419 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14420 TRPMResetTrap(pVCpu);
14421 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPF);
14422 return rc;
14423 }
14424
14425 if (rc == VINF_EM_RAW_GUEST_TRAP)
14426 {
14427 if (!pVmxTransient->fVectoringDoublePF)
14428 {
14429 /* It's a guest page fault and needs to be reflected to the guest. */
14430 uint32_t uGstErrorCode = TRPMGetErrorCode(pVCpu);
14431 TRPMResetTrap(pVCpu);
14432 pVCpu->hm.s.Event.fPending = false; /* In case it's a contributory #PF. */
14433 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), 0 /* cbInstr */,
14434 uGstErrorCode, pVmxTransient->uExitQual);
14435 }
14436 else
14437 {
14438 /* A guest page-fault occurred during delivery of a page-fault. Inject #DF. */
14439 TRPMResetTrap(pVCpu);
14440 pVCpu->hm.s.Event.fPending = false; /* Clear pending #PF to replace it with #DF. */
14441 hmR0VmxSetPendingXcptDF(pVCpu);
14442 Log4Func(("#PF: Pending #DF due to vectoring #PF\n"));
14443 }
14444
14445 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF);
14446 return VINF_SUCCESS;
14447 }
14448
14449 TRPMResetTrap(pVCpu);
14450 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitShadowPFEM);
14451 return rc;
14452}
14453
14454
14455/**
14456 * VM-exit exception handler for \#MF (Math Fault: floating point exception).
14457 *
14458 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14459 */
14460static VBOXSTRICTRC hmR0VmxExitXcptMF(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14461{
14462 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14463 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF);
14464
14465 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR0);
14466 AssertRCReturn(rc, rc);
14467
14468 if (!(pVCpu->cpum.GstCtx.cr0 & X86_CR0_NE))
14469 {
14470 /* Convert a #MF into a FERR -> IRQ 13. See @bugref{6117}. */
14471 rc = PDMIsaSetIrq(pVCpu->CTX_SUFF(pVM), 13, 1, 0 /* uTagSrc */);
14472
14473 /** @todo r=ramshankar: The Intel spec. does -not- specify that this VM-exit
14474 * provides VM-exit instruction length. If this causes problem later,
14475 * disassemble the instruction like it's done on AMD-V. */
14476 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14477 AssertRCReturn(rc2, rc2);
14478 return rc;
14479 }
14480
14481 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14482 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14483 return VINF_SUCCESS;
14484}
14485
14486
14487/**
14488 * VM-exit exception handler for \#BP (Breakpoint exception).
14489 *
14490 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14491 */
14492static VBOXSTRICTRC hmR0VmxExitXcptBP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14493{
14494 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14495 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP);
14496
14497 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14498 AssertRCReturn(rc, rc);
14499
14500 if (!pVmxTransient->fIsNestedGuest)
14501 rc = DBGFRZTrap03Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(&pVCpu->cpum.GstCtx));
14502 else
14503 rc = VINF_EM_RAW_GUEST_TRAP;
14504 if (rc == VINF_EM_RAW_GUEST_TRAP)
14505 {
14506 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14507 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14508 }
14509
14510 Assert(rc == VINF_SUCCESS || rc == VINF_EM_RAW_GUEST_TRAP || rc == VINF_EM_DBG_BREAKPOINT);
14511 return rc;
14512}
14513
14514
14515/**
14516 * VM-exit exception handler for \#AC (Alignment-check exception).
14517 *
14518 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14519 */
14520static VBOXSTRICTRC hmR0VmxExitXcptAC(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14521{
14522 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14523 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC);
14524
14525 /* Re-inject it. We'll detect any nesting before getting here. */
14526 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14527 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14528 return VINF_SUCCESS;
14529}
14530
14531
14532/**
14533 * VM-exit exception handler for \#DB (Debug exception).
14534 *
14535 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14536 */
14537static VBOXSTRICTRC hmR0VmxExitXcptDB(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14538{
14539 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14540 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB);
14541
14542 /*
14543 * Get the DR6-like values from the Exit qualification and pass it to DBGF for processing.
14544 */
14545 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
14546 AssertRCReturn(rc, rc);
14547
14548 /* Refer Intel spec. Table 27-1. "Exit Qualifications for debug exceptions" for the format. */
14549 uint64_t const uDR6 = X86_DR6_INIT_VAL
14550 | (pVmxTransient->uExitQual & ( X86_DR6_B0 | X86_DR6_B1 | X86_DR6_B2 | X86_DR6_B3
14551 | X86_DR6_BD | X86_DR6_BS));
14552
14553 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14554 if (!pVmxTransient->fIsNestedGuest)
14555 rc = DBGFRZTrap01Handler(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx), uDR6, pVCpu->hm.s.fSingleInstruction);
14556 else
14557 rc = VINF_EM_RAW_GUEST_TRAP;
14558 Log6Func(("rc=%Rrc\n", rc));
14559 if (rc == VINF_EM_RAW_GUEST_TRAP)
14560 {
14561 /*
14562 * The exception was for the guest. Update DR6, DR7.GD and
14563 * IA32_DEBUGCTL.LBR before forwarding it.
14564 * See Intel spec. 27.1 "Architectural State before a VM-Exit".
14565 */
14566 VMMRZCallRing3Disable(pVCpu);
14567 HM_DISABLE_PREEMPT(pVCpu);
14568
14569 pCtx->dr[6] &= ~X86_DR6_B_MASK;
14570 pCtx->dr[6] |= uDR6;
14571 if (CPUMIsGuestDebugStateActive(pVCpu))
14572 ASMSetDR6(pCtx->dr[6]);
14573
14574 HM_RESTORE_PREEMPT();
14575 VMMRZCallRing3Enable(pVCpu);
14576
14577 rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_DR7);
14578 AssertRCReturn(rc, rc);
14579
14580 /* X86_DR7_GD will be cleared if DRx accesses should be trapped inside the guest. */
14581 pCtx->dr[7] &= ~X86_DR7_GD;
14582
14583 /* Paranoia. */
14584 pCtx->dr[7] &= ~X86_DR7_RAZ_MASK;
14585 pCtx->dr[7] |= X86_DR7_RA1_MASK;
14586
14587 rc = VMXWriteVmcs32(VMX_VMCS_GUEST_DR7, (uint32_t)pCtx->dr[7]);
14588 AssertRCReturn(rc, rc);
14589
14590 /*
14591 * Raise #DB in the guest.
14592 *
14593 * It is important to reflect exactly what the VM-exit gave us (preserving the
14594 * interruption-type) rather than use hmR0VmxSetPendingXcptDB() as the #DB could've
14595 * been raised while executing ICEBP (INT1) and not the regular #DB. Thus it may
14596 * trigger different handling in the CPU (like skipping DPL checks), see @bugref{6398}.
14597 *
14598 * Intel re-documented ICEBP/INT1 on May 2018 previously documented as part of
14599 * Intel 386, see Intel spec. 24.8.3 "VM-Entry Controls for Event Injection".
14600 */
14601 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14602 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14603 return VINF_SUCCESS;
14604 }
14605
14606 /*
14607 * Not a guest trap, must be a hypervisor related debug event then.
14608 * Update DR6 in case someone is interested in it.
14609 */
14610 AssertMsg(rc == VINF_EM_DBG_STEPPED || rc == VINF_EM_DBG_BREAKPOINT, ("%Rrc\n", rc));
14611 AssertReturn(pVmxTransient->fWasHyperDebugStateActive, VERR_HM_IPE_5);
14612 CPUMSetHyperDR6(pVCpu, uDR6);
14613
14614 return rc;
14615}
14616
14617
14618/**
14619 * Hacks its way around the lovely mesa driver's backdoor accesses.
14620 *
14621 * @sa hmR0SvmHandleMesaDrvGp.
14622 */
14623static int hmR0VmxHandleMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14624{
14625 LogFunc(("cs:rip=%#04x:%#RX64 rcx=%#RX64 rbx=%#RX64\n", pCtx->cs.Sel, pCtx->rip, pCtx->rcx, pCtx->rbx));
14626 RT_NOREF(pCtx);
14627
14628 /* For now we'll just skip the instruction. */
14629 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
14630}
14631
14632
14633/**
14634 * Checks if the \#GP'ing instruction is the mesa driver doing it's lovely
14635 * backdoor logging w/o checking what it is running inside.
14636 *
14637 * This recognizes an "IN EAX,DX" instruction executed in flat ring-3, with the
14638 * backdoor port and magic numbers loaded in registers.
14639 *
14640 * @returns true if it is, false if it isn't.
14641 * @sa hmR0SvmIsMesaDrvGp.
14642 */
14643DECLINLINE(bool) hmR0VmxIsMesaDrvGp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, PCPUMCTX pCtx)
14644{
14645 /* 0xed: IN eAX,dx */
14646 uint8_t abInstr[1];
14647 if (pVmxTransient->cbInstr != sizeof(abInstr))
14648 return false;
14649
14650 /* Check that it is #GP(0). */
14651 if (pVmxTransient->uExitIntErrorCode != 0)
14652 return false;
14653
14654 /* Check magic and port. */
14655 Assert(!(pCtx->fExtrn & (CPUMCTX_EXTRN_RAX | CPUMCTX_EXTRN_RDX | CPUMCTX_EXTRN_RCX)));
14656 /*Log(("hmR0VmxIsMesaDrvGp: rax=%RX64 rdx=%RX64\n", pCtx->rax, pCtx->rdx));*/
14657 if (pCtx->rax != UINT32_C(0x564d5868))
14658 return false;
14659 if (pCtx->dx != UINT32_C(0x5658))
14660 return false;
14661
14662 /* Flat ring-3 CS. */
14663 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_CS);
14664 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_CS));
14665 /*Log(("hmR0VmxIsMesaDrvGp: cs.Attr.n.u2Dpl=%d base=%Rx64\n", pCtx->cs.Attr.n.u2Dpl, pCtx->cs.u64Base));*/
14666 if (pCtx->cs.Attr.n.u2Dpl != 3)
14667 return false;
14668 if (pCtx->cs.u64Base != 0)
14669 return false;
14670
14671 /* Check opcode. */
14672 AssertCompile(HMVMX_CPUMCTX_EXTRN_ALL & CPUMCTX_EXTRN_RIP);
14673 Assert(!(pCtx->fExtrn & CPUMCTX_EXTRN_RIP));
14674 int rc = PGMPhysSimpleReadGCPtr(pVCpu, abInstr, pCtx->rip, sizeof(abInstr));
14675 /*Log(("hmR0VmxIsMesaDrvGp: PGMPhysSimpleReadGCPtr -> %Rrc %#x\n", rc, abInstr[0]));*/
14676 if (RT_FAILURE(rc))
14677 return false;
14678 if (abInstr[0] != 0xed)
14679 return false;
14680
14681 return true;
14682}
14683
14684
14685/**
14686 * VM-exit exception handler for \#GP (General-protection exception).
14687 *
14688 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14689 */
14690static VBOXSTRICTRC hmR0VmxExitXcptGP(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14691{
14692 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14693 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP);
14694
14695 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
14696 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14697 if (pVmcsInfo->RealMode.fRealOnV86Active)
14698 { /* likely */ }
14699 else
14700 {
14701#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14702 Assert(pVCpu->hm.s.fUsingDebugLoop || pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv || pVmxTransient->fIsNestedGuest);
14703#endif
14704 /*
14705 * If the guest is not in real-mode or we have unrestricted guest execution support, or if we are
14706 * executing a nested-guest, reflect #GP to the guest or nested-guest.
14707 */
14708 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14709 AssertRCReturn(rc, rc);
14710 Log4Func(("Gst: cs:rip=%#04x:%#RX64 ErrorCode=%#x cr0=%#RX64 cpl=%u tr=%#04x\n", pCtx->cs.Sel, pCtx->rip,
14711 pVmxTransient->uExitIntErrorCode, pCtx->cr0, CPUMGetGuestCPL(pVCpu), pCtx->tr.Sel));
14712
14713 if ( pVmxTransient->fIsNestedGuest
14714 || !pVCpu->hm.s.fTrapXcptGpForLovelyMesaDrv
14715 || !hmR0VmxIsMesaDrvGp(pVCpu, pVmxTransient, pCtx))
14716 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo),
14717 pVmxTransient->cbInstr, pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14718 else
14719 rc = hmR0VmxHandleMesaDrvGp(pVCpu, pVmxTransient, pCtx);
14720 return rc;
14721 }
14722
14723 Assert(CPUMIsGuestInRealModeEx(pCtx));
14724 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest);
14725 Assert(!pVmxTransient->fIsNestedGuest);
14726
14727 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
14728 AssertRCReturn(rc, rc);
14729
14730 VBOXSTRICTRC rcStrict = IEMExecOne(pVCpu);
14731 if (rcStrict == VINF_SUCCESS)
14732 {
14733 if (!CPUMIsGuestInRealModeEx(pCtx))
14734 {
14735 /*
14736 * The guest is no longer in real-mode, check if we can continue executing the
14737 * guest using hardware-assisted VMX. Otherwise, fall back to emulation.
14738 */
14739 pVmcsInfo->RealMode.fRealOnV86Active = false;
14740 if (HMCanExecuteVmxGuest(pVCpu, pCtx))
14741 {
14742 Log4Func(("Mode changed but guest still suitable for executing using hardware-assisted VMX\n"));
14743 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14744 }
14745 else
14746 {
14747 Log4Func(("Mode changed -> VINF_EM_RESCHEDULE\n"));
14748 rcStrict = VINF_EM_RESCHEDULE;
14749 }
14750 }
14751 else
14752 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
14753 }
14754 else if (rcStrict == VINF_IEM_RAISED_XCPT)
14755 {
14756 rcStrict = VINF_SUCCESS;
14757 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
14758 }
14759 return VBOXSTRICTRC_VAL(rcStrict);
14760}
14761
14762
14763/**
14764 * VM-exit exception handler wrapper for all other exceptions that are not handled
14765 * by a specific handler.
14766 *
14767 * This simply re-injects the exception back into the VM without any special
14768 * processing.
14769 *
14770 * @remarks Requires all fields in HMVMX_READ_XCPT_INFO to be read from the VMCS.
14771 */
14772static VBOXSTRICTRC hmR0VmxExitXcptOthers(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14773{
14774 HMVMX_VALIDATE_EXIT_XCPT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14775
14776#ifndef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14777 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14778 AssertMsg(pVCpu->hm.s.fUsingDebugLoop || pVmcsInfo->RealMode.fRealOnV86Active || pVmxTransient->fIsNestedGuest,
14779 ("uVector=%#x u32XcptBitmap=%#X32\n",
14780 VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo), pVmcsInfo->u32XcptBitmap));
14781 NOREF(pVmcsInfo);
14782#endif
14783
14784 /*
14785 * Re-inject the exception into the guest. This cannot be a double-fault condition which
14786 * would have been handled while checking exits due to event delivery.
14787 */
14788 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14789
14790#ifdef HMVMX_ALWAYS_TRAP_ALL_XCPTS
14791 int rc = hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_RIP);
14792 AssertRCReturn(rc, rc);
14793 Log4Func(("Reinjecting Xcpt. uVector=%#x cs:rip=%#04x:%#RX64\n", uVector, pCtx->cs.Sel, pCtx->rip));
14794#endif
14795
14796#ifdef VBOX_WITH_STATISTICS
14797 switch (uVector)
14798 {
14799 case X86_XCPT_DE: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDE); break;
14800 case X86_XCPT_DB: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDB); break;
14801 case X86_XCPT_BP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBP); break;
14802 case X86_XCPT_OF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14803 case X86_XCPT_BR: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestBR); break;
14804 case X86_XCPT_UD: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestUD); break;
14805 case X86_XCPT_NM: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestOF); break;
14806 case X86_XCPT_DF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestDF); break;
14807 case X86_XCPT_TS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestTS); break;
14808 case X86_XCPT_NP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestNP); break;
14809 case X86_XCPT_SS: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestSS); break;
14810 case X86_XCPT_GP: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestGP); break;
14811 case X86_XCPT_PF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestPF); break;
14812 case X86_XCPT_MF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestMF); break;
14813 case X86_XCPT_AC: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestAC); break;
14814 case X86_XCPT_XF: STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXF); break;
14815 default:
14816 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitGuestXcpUnk);
14817 break;
14818 }
14819#endif
14820
14821 /* We should never call this function for a page-fault, we'd need to pass on the fault address below otherwise. */
14822 Assert(!VMX_EXIT_INT_INFO_IS_XCPT_PF(pVmxTransient->uExitIntInfo));
14823 NOREF(uVector);
14824
14825 /* Re-inject the original exception into the guest. */
14826 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_INT_INFO(pVmxTransient->uExitIntInfo), pVmxTransient->cbInstr,
14827 pVmxTransient->uExitIntErrorCode, 0 /* GCPtrFaultAddress */);
14828 return VINF_SUCCESS;
14829}
14830
14831
14832/**
14833 * VM-exit exception handler for all exceptions.
14834 *
14835 * @remarks This may be called for both guests and nested-guests. Take care to not
14836 * make assumptions and avoid doing anything that is not relevant when
14837 * executing a nested-guest (e.g., Mesa driver hacks).
14838 */
14839DECL_FORCE_INLINE(VBOXSTRICTRC) hmR0VmxExitXcptAll(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient, uint8_t uVector)
14840{
14841 /*
14842 * Validate we have read the required fields from the VMCS.
14843 */
14844#ifdef VBOX_STRICT
14845 uint32_t const fVmcsFieldRead = ASMAtomicUoReadU32(&pVmxTransient->fVmcsFieldsRead);
14846 RT_UNTRUSTED_NONVOLATILE_COPY_FENCE();
14847 Assert((fVmcsFieldRead & HMVMX_READ_XCPT_INFO) == HMVMX_READ_XCPT_INFO);
14848#endif
14849
14850 switch (uVector)
14851 {
14852 case X86_XCPT_PF: return hmR0VmxExitXcptPF(pVCpu, pVmxTransient);
14853 case X86_XCPT_GP: return hmR0VmxExitXcptGP(pVCpu, pVmxTransient);
14854 case X86_XCPT_MF: return hmR0VmxExitXcptMF(pVCpu, pVmxTransient);
14855 case X86_XCPT_DB: return hmR0VmxExitXcptDB(pVCpu, pVmxTransient);
14856 case X86_XCPT_BP: return hmR0VmxExitXcptBP(pVCpu, pVmxTransient);
14857 case X86_XCPT_AC: return hmR0VmxExitXcptAC(pVCpu, pVmxTransient);
14858 default:
14859 return hmR0VmxExitXcptOthers(pVCpu, pVmxTransient);
14860 }
14861}
14862/** @} */
14863
14864
14865/** @name VM-exit handlers.
14866 * @{
14867 */
14868/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14869/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- */
14870/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
14871
14872/**
14873 * VM-exit handler for external interrupts (VMX_EXIT_EXT_INT).
14874 */
14875HMVMX_EXIT_DECL hmR0VmxExitExtInt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14876{
14877 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14878 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitExtInt);
14879 /* Windows hosts (32-bit and 64-bit) have DPC latency issues. See @bugref{6853}. */
14880 if (VMMR0ThreadCtxHookIsEnabled(pVCpu))
14881 return VINF_SUCCESS;
14882 return VINF_EM_RAW_INTERRUPT;
14883}
14884
14885
14886/**
14887 * VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI). Conditional
14888 * VM-exit.
14889 */
14890HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmi(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14891{
14892 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14893 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitXcptNmi, y3);
14894
14895 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
14896 AssertRCReturn(rc, rc);
14897
14898 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(pVmxTransient->uExitIntInfo);
14899 uint32_t const uVector = VMX_EXIT_INT_INFO_VECTOR(pVmxTransient->uExitIntInfo);
14900 Assert(VMX_EXIT_INT_INFO_IS_VALID(pVmxTransient->uExitIntInfo));
14901
14902 PCVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14903 Assert( !(pVmcsInfo->u32ExitCtls & VMX_EXIT_CTLS_ACK_EXT_INT)
14904 && uExitIntType != VMX_EXIT_INT_INFO_TYPE_EXT_INT);
14905 NOREF(pVmcsInfo);
14906
14907 VBOXSTRICTRC rcStrict;
14908 switch (uExitIntType)
14909 {
14910 /*
14911 * Host physical NMIs:
14912 * This cannot be a guest NMI as the only way for the guest to receive an NMI is if we
14913 * injected it ourselves and anything we inject is not going to cause a VM-exit directly
14914 * for the event being injected[1]. Go ahead and dispatch the NMI to the host[2].
14915 *
14916 * See Intel spec. 27.2.3 "Information for VM Exits During Event Delivery".
14917 * See Intel spec. 27.5.5 "Updating Non-Register State".
14918 */
14919 case VMX_EXIT_INT_INFO_TYPE_NMI:
14920 {
14921 rcStrict = hmR0VmxExitHostNmi(pVCpu, pVmcsInfo);
14922 break;
14923 }
14924
14925 /*
14926 * Privileged software exceptions (#DB from ICEBP),
14927 * Software exceptions (#BP and #OF),
14928 * Hardware exceptions:
14929 * Process the required exceptions and resume guest execution if possible.
14930 */
14931 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
14932 Assert(uVector == X86_XCPT_DB);
14933 RT_FALL_THRU();
14934 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
14935 Assert(uVector == X86_XCPT_BP || uVector == X86_XCPT_OF || uExitIntType == VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT);
14936 RT_FALL_THRU();
14937 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
14938 {
14939 rc = hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
14940 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
14941 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
14942 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
14943 AssertRCReturn(rc, rc);
14944
14945 /*
14946 * If this VM-exit occurred while delivering an event through the guest IDT, take
14947 * action based on the return code and additional hints (e.g. for page-faults)
14948 * that will be updated in the VMX transient structure.
14949 */
14950 rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
14951 if (rcStrict == VINF_SUCCESS)
14952 {
14953 /*
14954 * If an exception caused a VM-exit due to delivery of an event, the original
14955 * event may have to be re-injected into the guest. We shall reinject it and
14956 * continue guest execution. However, page-fault is a complicated case and
14957 * needs additional processing done in hmR0VmxExitXcptPF().
14958 */
14959 if ( !pVCpu->hm.s.Event.fPending
14960 || uVector == X86_XCPT_PF)
14961 rcStrict = hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector);
14962 }
14963 else if (rcStrict == VINF_HM_DOUBLE_FAULT)
14964 {
14965 Assert(pVCpu->hm.s.Event.fPending);
14966 rcStrict = VINF_SUCCESS;
14967 }
14968 break;
14969 }
14970
14971 default:
14972 {
14973 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
14974 rcStrict = VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
14975 AssertMsgFailed(("Invalid/unexpected VM-exit interruption info %#x\n", pVmxTransient->uExitIntInfo));
14976 break;
14977 }
14978 }
14979
14980 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitXcptNmi, y3);
14981 return rcStrict;
14982}
14983
14984
14985/**
14986 * VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
14987 */
14988HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
14989{
14990 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
14991
14992 /* Indicate that we no longer need to VM-exit when the guest is ready to receive interrupts, it is now ready. */
14993 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
14994 int rc = hmR0VmxClearIntWindowExitVmcs(pVmcsInfo);
14995 AssertRCReturn(rc, rc);
14996
14997 /* Evaluate and deliver pending events and resume guest execution. */
14998 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIntWindow);
14999 return VINF_SUCCESS;
15000}
15001
15002
15003/**
15004 * VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
15005 */
15006HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindow(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15007{
15008 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15009
15010 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15011 if (RT_UNLIKELY(!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_NMI_WINDOW_EXIT))) /** @todo NSTVMX: Turn this into an assertion. */
15012 {
15013 AssertMsgFailed(("Unexpected NMI-window exit.\n"));
15014 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15015 }
15016
15017 Assert(!CPUMIsGuestNmiBlocking(pVCpu));
15018
15019 /*
15020 * If block-by-STI is set when we get this VM-exit, it means the CPU doesn't block NMIs following STI.
15021 * It is therefore safe to unblock STI and deliver the NMI ourselves. See @bugref{7445}.
15022 */
15023 uint32_t fIntrState;
15024 int rc = VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15025 AssertRCReturn(rc, rc);
15026 Assert(!(fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_MOVSS));
15027 if (fIntrState & VMX_VMCS_GUEST_INT_STATE_BLOCK_STI)
15028 {
15029 if (VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS))
15030 VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_INHIBIT_INTERRUPTS);
15031
15032 fIntrState &= ~VMX_VMCS_GUEST_INT_STATE_BLOCK_STI;
15033 rc = VMXWriteVmcs32(VMX_VMCS32_GUEST_INT_STATE, fIntrState);
15034 AssertRCReturn(rc, rc);
15035 }
15036
15037 /* Indicate that we no longer need to VM-exit when the guest is ready to receive NMIs, it is now ready */
15038 rc = hmR0VmxClearNmiWindowExitVmcs(pVmcsInfo);
15039 AssertRCReturn(rc, rc);
15040
15041 /* Evaluate and deliver pending events and resume guest execution. */
15042 return VINF_SUCCESS;
15043}
15044
15045
15046/**
15047 * VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
15048 */
15049HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15050{
15051 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15052 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15053}
15054
15055
15056/**
15057 * VM-exit handler for INVD (VMX_EXIT_INVD). Unconditional VM-exit.
15058 */
15059HMVMX_EXIT_NSRC_DECL hmR0VmxExitInvd(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15060{
15061 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15062 return hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15063}
15064
15065
15066/**
15067 * VM-exit handler for CPUID (VMX_EXIT_CPUID). Unconditional VM-exit.
15068 */
15069HMVMX_EXIT_DECL hmR0VmxExitCpuid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15070{
15071 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15072
15073 /*
15074 * Get the state we need and update the exit history entry.
15075 */
15076 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15077 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15078 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15079 AssertRCReturn(rc, rc);
15080
15081 VBOXSTRICTRC rcStrict;
15082 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
15083 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_CPUID),
15084 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
15085 if (!pExitRec)
15086 {
15087 /*
15088 * Regular CPUID instruction execution.
15089 */
15090 rcStrict = IEMExecDecodedCpuid(pVCpu, pVmxTransient->cbInstr);
15091 if (rcStrict == VINF_SUCCESS)
15092 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15093 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15094 {
15095 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15096 rcStrict = VINF_SUCCESS;
15097 }
15098 }
15099 else
15100 {
15101 /*
15102 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
15103 */
15104 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15105 AssertRCReturn(rc2, rc2);
15106
15107 Log4(("CpuIdExit/%u: %04x:%08RX64: %#x/%#x -> EMHistoryExec\n",
15108 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, pVCpu->cpum.GstCtx.eax, pVCpu->cpum.GstCtx.ecx));
15109
15110 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
15111 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
15112
15113 Log4(("CpuIdExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
15114 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
15115 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
15116 }
15117 return rcStrict;
15118}
15119
15120
15121/**
15122 * VM-exit handler for GETSEC (VMX_EXIT_GETSEC). Unconditional VM-exit.
15123 */
15124HMVMX_EXIT_DECL hmR0VmxExitGetsec(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15125{
15126 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15127
15128 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15129 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4);
15130 AssertRCReturn(rc, rc);
15131
15132 if (pVCpu->cpum.GstCtx.cr4 & X86_CR4_SMXE)
15133 return VINF_EM_RAW_EMULATE_INSTR;
15134
15135 AssertMsgFailed(("hmR0VmxExitGetsec: Unexpected VM-exit when CR4.SMXE is 0.\n"));
15136 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15137}
15138
15139
15140/**
15141 * VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
15142 */
15143HMVMX_EXIT_DECL hmR0VmxExitRdtsc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15144{
15145 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15146
15147 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15148 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15149 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15150 AssertRCReturn(rc, rc);
15151
15152 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtsc(pVCpu, pVmxTransient->cbInstr);
15153 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15154 {
15155 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15156 we must reset offsetting on VM-entry. See @bugref{6634}. */
15157 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15158 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15159 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15160 }
15161 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15162 {
15163 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15164 rcStrict = VINF_SUCCESS;
15165 }
15166 return rcStrict;
15167}
15168
15169
15170/**
15171 * VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
15172 */
15173HMVMX_EXIT_DECL hmR0VmxExitRdtscp(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15174{
15175 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15176
15177 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15178 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_TSC_AUX);
15179 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15180 AssertRCReturn(rc, rc);
15181
15182 VBOXSTRICTRC rcStrict = IEMExecDecodedRdtscp(pVCpu, pVmxTransient->cbInstr);
15183 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
15184 {
15185 /* If we get a spurious VM-exit when TSC offsetting is enabled,
15186 we must reset offsetting on VM-reentry. See @bugref{6634}. */
15187 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TSC_OFFSETTING)
15188 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15189 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15190 }
15191 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15192 {
15193 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15194 rcStrict = VINF_SUCCESS;
15195 }
15196 return rcStrict;
15197}
15198
15199
15200/**
15201 * VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
15202 */
15203HMVMX_EXIT_DECL hmR0VmxExitRdpmc(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15204{
15205 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15206
15207 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15208 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_CR0
15209 | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_SS);
15210 AssertRCReturn(rc, rc);
15211
15212 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15213 rc = EMInterpretRdpmc(pVCpu->CTX_SUFF(pVM), pVCpu, CPUMCTX2CORE(pCtx));
15214 if (RT_LIKELY(rc == VINF_SUCCESS))
15215 {
15216 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15217 Assert(pVmxTransient->cbInstr == 2);
15218 }
15219 else
15220 {
15221 AssertMsgFailed(("hmR0VmxExitRdpmc: EMInterpretRdpmc failed with %Rrc\n", rc));
15222 rc = VERR_EM_INTERPRETER;
15223 }
15224 return rc;
15225}
15226
15227
15228/**
15229 * VM-exit handler for VMCALL (VMX_EXIT_VMCALL). Unconditional VM-exit.
15230 */
15231HMVMX_EXIT_DECL hmR0VmxExitVmcall(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15232{
15233 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15234
15235 VBOXSTRICTRC rcStrict = VERR_VMX_IPE_3;
15236 if (EMAreHypercallInstructionsEnabled(pVCpu))
15237 {
15238 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15239 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_RIP | CPUMCTX_EXTRN_RFLAGS | CPUMCTX_EXTRN_CR0
15240 | CPUMCTX_EXTRN_SS | CPUMCTX_EXTRN_CS | CPUMCTX_EXTRN_EFER);
15241 AssertRCReturn(rc, rc);
15242
15243 /* Perform the hypercall. */
15244 rcStrict = GIMHypercall(pVCpu, &pVCpu->cpum.GstCtx);
15245 if (rcStrict == VINF_SUCCESS)
15246 {
15247 rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15248 AssertRCReturn(rc, rc);
15249 }
15250 else
15251 Assert( rcStrict == VINF_GIM_R3_HYPERCALL
15252 || rcStrict == VINF_GIM_HYPERCALL_CONTINUING
15253 || RT_FAILURE(rcStrict));
15254
15255 /* If the hypercall changes anything other than guest's general-purpose registers,
15256 we would need to reload the guest changed bits here before VM-entry. */
15257 }
15258 else
15259 Log4Func(("Hypercalls not enabled\n"));
15260
15261 /* If hypercalls are disabled or the hypercall failed for some reason, raise #UD and continue. */
15262 if (RT_FAILURE(rcStrict))
15263 {
15264 hmR0VmxSetPendingXcptUD(pVCpu);
15265 rcStrict = VINF_SUCCESS;
15266 }
15267
15268 return rcStrict;
15269}
15270
15271
15272/**
15273 * VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
15274 */
15275HMVMX_EXIT_DECL hmR0VmxExitInvlpg(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15276{
15277 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15278 Assert(!pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging || pVCpu->hm.s.fUsingDebugLoop);
15279
15280 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15281 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15282 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15283 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
15284 AssertRCReturn(rc, rc);
15285
15286 VBOXSTRICTRC rcStrict = IEMExecDecodedInvlpg(pVCpu, pVmxTransient->cbInstr, pVmxTransient->uExitQual);
15287
15288 if (rcStrict == VINF_SUCCESS || rcStrict == VINF_PGM_SYNC_CR3)
15289 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15290 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15291 {
15292 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15293 rcStrict = VINF_SUCCESS;
15294 }
15295 else
15296 AssertMsgFailed(("Unexpected IEMExecDecodedInvlpg(%#RX64) status: %Rrc\n", pVmxTransient->uExitQual,
15297 VBOXSTRICTRC_VAL(rcStrict)));
15298 return rcStrict;
15299}
15300
15301
15302/**
15303 * VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
15304 */
15305HMVMX_EXIT_DECL hmR0VmxExitMonitor(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15306{
15307 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15308
15309 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15310 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK | CPUMCTX_EXTRN_DS);
15311 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15312 AssertRCReturn(rc, rc);
15313
15314 VBOXSTRICTRC rcStrict = IEMExecDecodedMonitor(pVCpu, pVmxTransient->cbInstr);
15315 if (rcStrict == VINF_SUCCESS)
15316 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15317 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15318 {
15319 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15320 rcStrict = VINF_SUCCESS;
15321 }
15322
15323 return rcStrict;
15324}
15325
15326
15327/**
15328 * VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
15329 */
15330HMVMX_EXIT_DECL hmR0VmxExitMwait(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15331{
15332 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15333
15334 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15335 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
15336 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15337 AssertRCReturn(rc, rc);
15338
15339 VBOXSTRICTRC rcStrict = IEMExecDecodedMwait(pVCpu, pVmxTransient->cbInstr);
15340 if (RT_SUCCESS(rcStrict))
15341 {
15342 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15343 if (EMMonitorWaitShouldContinue(pVCpu, &pVCpu->cpum.GstCtx))
15344 rcStrict = VINF_SUCCESS;
15345 }
15346
15347 return rcStrict;
15348}
15349
15350
15351/**
15352 * VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT). Unconditional
15353 * VM-exit.
15354 */
15355HMVMX_EXIT_DECL hmR0VmxExitTripleFault(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15356{
15357 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15358 return VINF_EM_RESET;
15359}
15360
15361
15362/**
15363 * VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
15364 */
15365HMVMX_EXIT_DECL hmR0VmxExitHlt(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15366{
15367 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15368
15369 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15370 AssertRCReturn(rc, rc);
15371
15372 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_RFLAGS); /* Advancing the RIP above should've imported eflags. */
15373 if (EMShouldContinueAfterHalt(pVCpu, &pVCpu->cpum.GstCtx)) /* Requires eflags. */
15374 rc = VINF_SUCCESS;
15375 else
15376 rc = VINF_EM_HALT;
15377
15378 if (rc != VINF_SUCCESS)
15379 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchHltToR3);
15380 return rc;
15381}
15382
15383
15384/**
15385 * VM-exit handler for instructions that result in a \#UD exception delivered to
15386 * the guest.
15387 */
15388HMVMX_EXIT_NSRC_DECL hmR0VmxExitSetPendingXcptUD(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15389{
15390 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15391 hmR0VmxSetPendingXcptUD(pVCpu);
15392 return VINF_SUCCESS;
15393}
15394
15395
15396/**
15397 * VM-exit handler for expiry of the VMX-preemption timer.
15398 */
15399HMVMX_EXIT_DECL hmR0VmxExitPreemptTimer(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15400{
15401 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15402
15403 /* If the VMX-preemption timer has expired, reinitialize the preemption timer on next VM-entry. */
15404 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15405
15406 /* If there are any timer events pending, fall back to ring-3, otherwise resume guest execution. */
15407 PVM pVM = pVCpu->CTX_SUFF(pVM);
15408 bool fTimersPending = TMTimerPollBool(pVM, pVCpu);
15409 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitPreemptTimer);
15410 return fTimersPending ? VINF_EM_RAW_TIMER_PENDING : VINF_SUCCESS;
15411}
15412
15413
15414/**
15415 * VM-exit handler for XSETBV (VMX_EXIT_XSETBV). Unconditional VM-exit.
15416 */
15417HMVMX_EXIT_DECL hmR0VmxExitXsetbv(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15418{
15419 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15420
15421 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15422 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15423 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_CR4);
15424 AssertRCReturn(rc, rc);
15425
15426 VBOXSTRICTRC rcStrict = IEMExecDecodedXsetbv(pVCpu, pVmxTransient->cbInstr);
15427 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, rcStrict != VINF_IEM_RAISED_XCPT ? HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15428 : HM_CHANGED_RAISED_XCPT_MASK);
15429
15430 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
15431 pVCpu->hm.s.fLoadSaveGuestXcr0 = (pCtx->cr4 & X86_CR4_OSXSAVE) && pCtx->aXcr[0] != ASMGetXcr0();
15432
15433 return rcStrict;
15434}
15435
15436
15437/**
15438 * VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
15439 */
15440HMVMX_EXIT_DECL hmR0VmxExitInvpcid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15441{
15442 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15443 /** @todo Use VM-exit instruction information. */
15444 return VERR_EM_INTERPRETER;
15445}
15446
15447
15448/**
15449 * VM-exit handler for invalid-guest-state (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error
15450 * VM-exit.
15451 */
15452HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrInvalidGuestState(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15453{
15454 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15455 int rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
15456 AssertRCReturn(rc, rc);
15457
15458 rc = hmR0VmxCheckVmcsCtls(pVCpu, pVmcsInfo, pVmxTransient->fIsNestedGuest);
15459 if (RT_FAILURE(rc))
15460 return rc;
15461
15462 uint32_t const uInvalidReason = hmR0VmxCheckGuestState(pVCpu, pVmcsInfo);
15463 NOREF(uInvalidReason);
15464
15465#ifdef VBOX_STRICT
15466 uint32_t fIntrState;
15467 RTHCUINTREG uHCReg;
15468 uint64_t u64Val;
15469 uint32_t u32Val;
15470 rc = hmR0VmxReadEntryIntInfoVmcs(pVmxTransient);
15471 rc |= hmR0VmxReadEntryXcptErrorCodeVmcs(pVmxTransient);
15472 rc |= hmR0VmxReadEntryInstrLenVmcs(pVmxTransient);
15473 rc |= VMXReadVmcs32(VMX_VMCS32_GUEST_INT_STATE, &fIntrState);
15474 AssertRCReturn(rc, rc);
15475
15476 Log4(("uInvalidReason %u\n", uInvalidReason));
15477 Log4(("VMX_VMCS32_CTRL_ENTRY_INTERRUPTION_INFO %#RX32\n", pVmxTransient->uEntryIntInfo));
15478 Log4(("VMX_VMCS32_CTRL_ENTRY_EXCEPTION_ERRCODE %#RX32\n", pVmxTransient->uEntryXcptErrorCode));
15479 Log4(("VMX_VMCS32_CTRL_ENTRY_INSTR_LENGTH %#RX32\n", pVmxTransient->cbEntryInstr));
15480 Log4(("VMX_VMCS32_GUEST_INT_STATE %#RX32\n", fIntrState));
15481
15482 rc = VMXReadVmcs32(VMX_VMCS_GUEST_CR0, &u32Val); AssertRC(rc);
15483 Log4(("VMX_VMCS_GUEST_CR0 %#RX32\n", u32Val));
15484 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_MASK, &uHCReg); AssertRC(rc);
15485 Log4(("VMX_VMCS_CTRL_CR0_MASK %#RHr\n", uHCReg));
15486 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR0_READ_SHADOW, &uHCReg); AssertRC(rc);
15487 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15488 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_MASK, &uHCReg); AssertRC(rc);
15489 Log4(("VMX_VMCS_CTRL_CR4_MASK %#RHr\n", uHCReg));
15490 rc = VMXReadVmcsHstN(VMX_VMCS_CTRL_CR4_READ_SHADOW, &uHCReg); AssertRC(rc);
15491 Log4(("VMX_VMCS_CTRL_CR4_READ_SHADOW %#RHr\n", uHCReg));
15492 if (pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging)
15493 {
15494 rc = VMXReadVmcs64(VMX_VMCS64_CTRL_EPTP_FULL, &u64Val); AssertRC(rc);
15495 Log4(("VMX_VMCS64_CTRL_EPTP_FULL %#RX64\n", u64Val));
15496 }
15497
15498 hmR0DumpRegs(pVCpu);
15499#endif
15500
15501 return VERR_VMX_INVALID_GUEST_STATE;
15502}
15503
15504/**
15505 * VM-exit handler for all undefined/unexpected reasons. Should never happen.
15506 */
15507HMVMX_EXIT_NSRC_DECL hmR0VmxExitErrUnexpected(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15508{
15509 /*
15510 * Cummulative notes of all recognized but unexpected VM-exits.
15511 *
15512 * 1. This does -not- cover scenarios like like a page-fault VM-exit occurring when
15513 * nested-paging is used.
15514 *
15515 * 2. Any instruction that causes a VM-exit unconditionally (for e.g. VMXON) must be
15516 * emulated or a #UD must be raised in the guest. Therefore, we should -not- be using
15517 * this function (and thereby stop VM execution) for handling such instructions.
15518 *
15519 *
15520 * VMX_EXIT_INIT_SIGNAL:
15521 * INIT signals are blocked in VMX root operation by VMXON and by SMI in SMM.
15522 * It is -NOT- blocked in VMX non-root operation so we can, in theory, still get these
15523 * VM-exits. However, we should not receive INIT signals VM-exit while executing a VM.
15524 *
15525 * See Intel spec. 33.14.1 Default Treatment of SMI Delivery"
15526 * See Intel spec. 29.3 "VMX Instructions" for "VMXON".
15527 * See Intel spec. "23.8 Restrictions on VMX operation".
15528 *
15529 * VMX_EXIT_SIPI:
15530 * SIPI exits can only occur in VMX non-root operation when the "wait-for-SIPI" guest
15531 * activity state is used. We don't make use of it as our guests don't have direct
15532 * access to the host local APIC.
15533 *
15534 * See Intel spec. 25.3 "Other Causes of VM-exits".
15535 *
15536 * VMX_EXIT_IO_SMI:
15537 * VMX_EXIT_SMI:
15538 * This can only happen if we support dual-monitor treatment of SMI, which can be
15539 * activated by executing VMCALL in VMX root operation. Only an STM (SMM transfer
15540 * monitor) would get this VM-exit when we (the executive monitor) execute a VMCALL in
15541 * VMX root mode or receive an SMI. If we get here, something funny is going on.
15542 *
15543 * See Intel spec. 33.15.6 "Activating the Dual-Monitor Treatment"
15544 * See Intel spec. 25.3 "Other Causes of VM-Exits"
15545 *
15546 * VMX_EXIT_ERR_MSR_LOAD:
15547 * Failures while loading MSRs are part of the VM-entry MSR-load area are unexpected
15548 * and typically indicates a bug in the hypervisor code. We thus cannot not resume
15549 * execution.
15550 *
15551 * See Intel spec. 26.7 "VM-Entry Failures During Or After Loading Guest State".
15552 *
15553 * VMX_EXIT_ERR_MACHINE_CHECK:
15554 * Machine check exceptions indicates a fatal/unrecoverable hardware condition
15555 * including but not limited to system bus, ECC, parity, cache and TLB errors. A
15556 * #MC exception abort class exception is raised. We thus cannot assume a
15557 * reasonable chance of continuing any sort of execution and we bail.
15558 *
15559 * See Intel spec. 15.1 "Machine-check Architecture".
15560 * See Intel spec. 27.1 "Architectural State Before A VM Exit".
15561 *
15562 * VMX_EXIT_PML_FULL:
15563 * VMX_EXIT_VIRTUALIZED_EOI:
15564 * VMX_EXIT_APIC_WRITE:
15565 * We do not currently support any of these features and thus they are all unexpected
15566 * VM-exits.
15567 *
15568 * VMX_EXIT_GDTR_IDTR_ACCESS:
15569 * VMX_EXIT_LDTR_TR_ACCESS:
15570 * VMX_EXIT_RDRAND:
15571 * VMX_EXIT_RSM:
15572 * VMX_EXIT_VMFUNC:
15573 * VMX_EXIT_ENCLS:
15574 * VMX_EXIT_RDSEED:
15575 * VMX_EXIT_XSAVES:
15576 * VMX_EXIT_XRSTORS:
15577 * VMX_EXIT_UMWAIT:
15578 * VMX_EXIT_TPAUSE:
15579 * These VM-exits are -not- caused unconditionally by execution of the corresponding
15580 * instruction. Any VM-exit for these instructions indicate a hardware problem,
15581 * unsupported CPU modes (like SMM) or potentially corrupt VMCS controls.
15582 *
15583 * See Intel spec. 25.1.3 "Instructions That Cause VM Exits Conditionally".
15584 */
15585 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15586 AssertMsgFailed(("Unexpected VM-exit %u\n", pVmxTransient->uExitReason));
15587 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
15588}
15589
15590
15591/**
15592 * VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
15593 */
15594HMVMX_EXIT_DECL hmR0VmxExitRdmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15595{
15596 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15597
15598 /** @todo Optimize this: We currently drag in in the whole MSR state
15599 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15600 * MSRs required. That would require changes to IEM and possibly CPUM too.
15601 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15602 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15603 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15604 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15605 switch (idMsr)
15606 {
15607 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15608 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15609 }
15610
15611 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15612 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15613 AssertRCReturn(rc, rc);
15614
15615 Log4Func(("ecx=%#RX32\n", idMsr));
15616
15617#ifdef VBOX_STRICT
15618 Assert(!pVmxTransient->fIsNestedGuest);
15619 if (pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS)
15620 {
15621 if ( hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr)
15622 && idMsr != MSR_K6_EFER)
15623 {
15624 AssertMsgFailed(("Unexpected RDMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n", idMsr));
15625 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15626 }
15627 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15628 {
15629 Assert(pVmcsInfo->pvMsrBitmap);
15630 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15631 if (fMsrpm & VMXMSRPM_ALLOW_RD)
15632 {
15633 AssertMsgFailed(("Unexpected RDMSR for a passthru lazy-restore MSR. ecx=%#RX32\n", idMsr));
15634 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15635 }
15636 }
15637 }
15638#endif
15639
15640 VBOXSTRICTRC rcStrict = IEMExecDecodedRdmsr(pVCpu, pVmxTransient->cbInstr);
15641 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitRdmsr);
15642 if (rcStrict == VINF_SUCCESS)
15643 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS
15644 | HM_CHANGED_GUEST_RAX | HM_CHANGED_GUEST_RDX);
15645 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15646 {
15647 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15648 rcStrict = VINF_SUCCESS;
15649 }
15650 else
15651 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_READ, ("Unexpected IEMExecDecodedRdmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15652
15653 return rcStrict;
15654}
15655
15656
15657/**
15658 * VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
15659 */
15660HMVMX_EXIT_DECL hmR0VmxExitWrmsr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15661{
15662 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15663
15664 /** @todo Optimize this: We currently drag in in the whole MSR state
15665 * (CPUMCTX_EXTRN_ALL_MSRS) here. We should optimize this to only get
15666 * MSRs required. That would require changes to IEM and possibly CPUM too.
15667 * (Should probably do it lazy fashion from CPUMAllMsrs.cpp). */
15668 uint32_t const idMsr = pVCpu->cpum.GstCtx.ecx;
15669 uint64_t fImport = IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK | CPUMCTX_EXTRN_ALL_MSRS;
15670
15671 /*
15672 * The FS and GS base MSRs are not part of the above all-MSRs mask.
15673 * Although we don't need to fetch the base as it will be overwritten shortly, while
15674 * loading guest-state we would also load the entire segment register including limit
15675 * and attributes and thus we need to load them here.
15676 */
15677 switch (idMsr)
15678 {
15679 case MSR_K8_FS_BASE: fImport |= CPUMCTX_EXTRN_FS; break;
15680 case MSR_K8_GS_BASE: fImport |= CPUMCTX_EXTRN_GS; break;
15681 }
15682
15683 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15684 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15685 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, fImport);
15686 AssertRCReturn(rc, rc);
15687
15688 Log4Func(("ecx=%#RX32 edx:eax=%#RX32:%#RX32\n", idMsr, pVCpu->cpum.GstCtx.edx, pVCpu->cpum.GstCtx.eax));
15689
15690 VBOXSTRICTRC rcStrict = IEMExecDecodedWrmsr(pVCpu, pVmxTransient->cbInstr);
15691 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitWrmsr);
15692
15693 if (rcStrict == VINF_SUCCESS)
15694 {
15695 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
15696
15697 /* If this is an X2APIC WRMSR access, update the APIC state as well. */
15698 if ( idMsr == MSR_IA32_APICBASE
15699 || ( idMsr >= MSR_IA32_X2APIC_START
15700 && idMsr <= MSR_IA32_X2APIC_END))
15701 {
15702 /*
15703 * We've already saved the APIC related guest-state (TPR) in post-run phase.
15704 * When full APIC register virtualization is implemented we'll have to make
15705 * sure APIC state is saved from the VMCS before IEM changes it.
15706 */
15707 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_APIC_TPR);
15708 }
15709 else if (idMsr == MSR_IA32_TSC) /* Windows 7 does this during bootup. See @bugref{6398}. */
15710 pVmxTransient->fUpdatedTscOffsettingAndPreemptTimer = false;
15711 else if (idMsr == MSR_K6_EFER)
15712 {
15713 /*
15714 * If the guest touches the EFER MSR we need to update the VM-Entry and VM-Exit controls
15715 * as well, even if it is -not- touching bits that cause paging mode changes (LMA/LME).
15716 * We care about the other bits as well, SCE and NXE. See @bugref{7368}.
15717 */
15718 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_EFER_MSR | HM_CHANGED_VMX_ENTRY_EXIT_CTLS);
15719 }
15720
15721 /* Update MSRs that are part of the VMCS and auto-load/store area when MSR-bitmaps are not used. */
15722 if (!(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_MSR_BITMAPS))
15723 {
15724 switch (idMsr)
15725 {
15726 case MSR_IA32_SYSENTER_CS: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_CS_MSR); break;
15727 case MSR_IA32_SYSENTER_EIP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_EIP_MSR); break;
15728 case MSR_IA32_SYSENTER_ESP: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_SYSENTER_ESP_MSR); break;
15729 case MSR_K8_FS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_FS); break;
15730 case MSR_K8_GS_BASE: ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_GS); break;
15731 case MSR_K6_EFER: /* Nothing to do, already handled above. */ break;
15732 default:
15733 {
15734 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15735 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_AUTO_MSRS);
15736 else if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15737 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_VMX_GUEST_LAZY_MSRS);
15738 break;
15739 }
15740 }
15741 }
15742#ifdef VBOX_STRICT
15743 else
15744 {
15745 /* Paranoia. Validate that MSRs in the MSR-bitmaps with write-passthru are not intercepted. */
15746 switch (idMsr)
15747 {
15748 case MSR_IA32_SYSENTER_CS:
15749 case MSR_IA32_SYSENTER_EIP:
15750 case MSR_IA32_SYSENTER_ESP:
15751 case MSR_K8_FS_BASE:
15752 case MSR_K8_GS_BASE:
15753 {
15754 AssertMsgFailed(("Unexpected WRMSR for an MSR in the VMCS. ecx=%#RX32\n", idMsr));
15755 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15756 }
15757
15758 /* Writes to MSRs in auto-load/store area/swapped MSRs, shouldn't cause VM-exits with MSR-bitmaps. */
15759 default:
15760 {
15761 if (hmR0VmxIsAutoLoadGuestMsr(pVmcsInfo, idMsr))
15762 {
15763 /* EFER MSR writes are always intercepted. */
15764 if (idMsr != MSR_K6_EFER)
15765 {
15766 AssertMsgFailed(("Unexpected WRMSR for an MSR in the auto-load/store area in the VMCS. ecx=%#RX32\n",
15767 idMsr));
15768 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15769 }
15770 }
15771
15772 if (hmR0VmxIsLazyGuestMsr(pVCpu, idMsr))
15773 {
15774 Assert(pVmcsInfo->pvMsrBitmap);
15775 uint32_t fMsrpm = CPUMGetVmxMsrPermission(pVmcsInfo->pvMsrBitmap, idMsr);
15776 if (fMsrpm & VMXMSRPM_ALLOW_WR)
15777 {
15778 AssertMsgFailed(("Unexpected WRMSR for passthru, lazy-restore MSR. ecx=%#RX32\n", idMsr));
15779 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, idMsr);
15780 }
15781 }
15782 break;
15783 }
15784 }
15785 }
15786#endif /* VBOX_STRICT */
15787 }
15788 else if (rcStrict == VINF_IEM_RAISED_XCPT)
15789 {
15790 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
15791 rcStrict = VINF_SUCCESS;
15792 }
15793 else
15794 AssertMsg(rcStrict == VINF_CPUM_R3_MSR_WRITE, ("Unexpected IEMExecDecodedWrmsr rc (%Rrc)\n", VBOXSTRICTRC_VAL(rcStrict)));
15795
15796 return rcStrict;
15797}
15798
15799
15800/**
15801 * VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
15802 */
15803HMVMX_EXIT_DECL hmR0VmxExitPause(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15804{
15805 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15806
15807 /** @todo The guest has likely hit a contended spinlock. We might want to
15808 * poke a schedule different guest VCPU. */
15809 int rc = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
15810 if (RT_SUCCESS(rc))
15811 return VINF_EM_RAW_INTERRUPT;
15812
15813 AssertMsgFailed(("hmR0VmxExitPause: Failed to increment RIP. rc=%Rrc\n", rc));
15814 return rc;
15815}
15816
15817
15818/**
15819 * VM-exit handler for when the TPR value is lowered below the specified
15820 * threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
15821 */
15822HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThreshold(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15823{
15824 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15825 Assert(pVmxTransient->pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW);
15826
15827 /*
15828 * The TPR shadow would've been synced with the APIC TPR in the post-run phase.
15829 * We'll re-evaluate pending interrupts and inject them before the next VM
15830 * entry so we can just continue execution here.
15831 */
15832 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTprBelowThreshold);
15833 return VINF_SUCCESS;
15834}
15835
15836
15837/**
15838 * VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX). Conditional
15839 * VM-exit.
15840 *
15841 * @retval VINF_SUCCESS when guest execution can continue.
15842 * @retval VINF_PGM_SYNC_CR3 CR3 sync is required, back to ring-3.
15843 * @retval VERR_EM_RESCHEDULE_REM when we need to return to ring-3 due to
15844 * incompatible guest state for VMX execution (real-on-v86 case).
15845 */
15846HMVMX_EXIT_DECL hmR0VmxExitMovCRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15847{
15848 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
15849 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitMovCRx, y2);
15850
15851 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
15852 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
15853 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
15854 AssertRCReturn(rc, rc);
15855
15856 VBOXSTRICTRC rcStrict;
15857 PVM pVM = pVCpu->CTX_SUFF(pVM);
15858 uint64_t const uExitQual = pVmxTransient->uExitQual;
15859 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(uExitQual);
15860 switch (uAccessType)
15861 {
15862 /*
15863 * MOV to CRx.
15864 */
15865 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
15866 {
15867 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
15868 AssertRCReturn(rc, rc);
15869
15870 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_CR0);
15871 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
15872 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15873 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15874
15875 /*
15876 * MOV to CR3 only cause a VM-exit when one or more of the following are true:
15877 * - When nested paging isn't used.
15878 * - If the guest doesn't have paging enabled (intercept CR3 to update shadow page tables).
15879 * - We are executing in the VM debug loop.
15880 */
15881 Assert( iCrReg != 3
15882 || !pVM->hm.s.fNestedPaging
15883 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15884 || pVCpu->hm.s.fUsingDebugLoop);
15885
15886 /* MOV to CR8 writes only cause VM-exits when TPR shadow is not used. */
15887 Assert( iCrReg != 8
15888 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15889
15890 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15891 AssertMsg( rcStrict == VINF_SUCCESS
15892 || rcStrict == VINF_PGM_SYNC_CR3, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
15893
15894 /*
15895 * This is a kludge for handling switches back to real mode when we try to use
15896 * V86 mode to run real mode code directly. Problem is that V86 mode cannot
15897 * deal with special selector values, so we have to return to ring-3 and run
15898 * there till the selector values are V86 mode compatible.
15899 *
15900 * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
15901 * latter is an alias for VINF_IEM_RAISED_XCPT which is asserted at the end of
15902 * this function.
15903 */
15904 if ( iCrReg == 0
15905 && rcStrict == VINF_SUCCESS
15906 && !pVM->hm.s.vmx.fUnrestrictedGuest
15907 && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
15908 && (uOldCr0 & X86_CR0_PE)
15909 && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
15910 {
15911 /** @todo Check selectors rather than returning all the time. */
15912 Assert(!pVmxTransient->fIsNestedGuest);
15913 Log4Func(("CR0 write, back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
15914 rcStrict = VINF_EM_RESCHEDULE_REM;
15915 }
15916 break;
15917 }
15918
15919 /*
15920 * MOV from CRx.
15921 */
15922 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
15923 {
15924 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(uExitQual);
15925 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(uExitQual);
15926
15927 /*
15928 * MOV from CR3 only cause a VM-exit when one or more of the following are true:
15929 * - When nested paging isn't used.
15930 * - If the guest doesn't have paging enabled (pass guest's CR3 rather than our identity mapped CR3).
15931 * - We are executing in the VM debug loop.
15932 */
15933 Assert( iCrReg != 3
15934 || !pVM->hm.s.fNestedPaging
15935 || !CPUMIsGuestPagingEnabledEx(&pVCpu->cpum.GstCtx)
15936 || pVCpu->hm.s.fUsingDebugLoop);
15937
15938 /* MOV from CR8 reads only cause a VM-exit when the TPR shadow feature isn't enabled. */
15939 Assert( iCrReg != 8
15940 || !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW));
15941
15942 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
15943 break;
15944 }
15945
15946 /*
15947 * CLTS (Clear Task-Switch Flag in CR0).
15948 */
15949 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
15950 {
15951 rcStrict = hmR0VmxExitClts(pVCpu, pVmcsInfo, pVmxTransient->cbInstr);
15952 break;
15953 }
15954
15955 /*
15956 * LMSW (Load Machine-Status Word into CR0).
15957 * LMSW cannot clear CR0.PE, so no fRealOnV86Active kludge needed here.
15958 */
15959 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW:
15960 {
15961 RTGCPTR GCPtrEffDst;
15962 uint8_t const cbInstr = pVmxTransient->cbInstr;
15963 uint16_t const uMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(uExitQual);
15964 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(uExitQual);
15965 if (fMemOperand)
15966 {
15967 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
15968 AssertRCReturn(rc, rc);
15969 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
15970 }
15971 else
15972 GCPtrEffDst = NIL_RTGCPTR;
15973 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmcsInfo, cbInstr, uMsw, GCPtrEffDst);
15974 break;
15975 }
15976
15977 default:
15978 {
15979 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
15980 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
15981 }
15982 }
15983
15984 Assert((pVCpu->hm.s.fCtxChanged & (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS))
15985 == (HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS));
15986 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
15987
15988 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitMovCRx, y2);
15989 NOREF(pVM);
15990 return rcStrict;
15991}
15992
15993
15994/**
15995 * VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR). Conditional
15996 * VM-exit.
15997 */
15998HMVMX_EXIT_DECL hmR0VmxExitIoInstr(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
15999{
16000 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16001 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitIO, y1);
16002
16003 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16004 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16005 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16006 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16007 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK | CPUMCTX_EXTRN_SREG_MASK
16008 | CPUMCTX_EXTRN_EFER);
16009 /* EFER MSR also required for longmode checks in EMInterpretDisasCurrent(), but it's always up-to-date. */
16010 AssertRCReturn(rc, rc);
16011
16012 /* Refer Intel spec. 27-5. "Exit Qualifications for I/O Instructions" for the format. */
16013 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
16014 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
16015 bool const fIOWrite = (VMX_EXIT_QUAL_IO_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_IO_DIRECTION_OUT);
16016 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
16017 bool const fGstStepping = RT_BOOL(pCtx->eflags.Bits.u1TF);
16018 bool const fDbgStepping = pVCpu->hm.s.fSingleInstruction;
16019 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
16020
16021 /*
16022 * Update exit history to see if this exit can be optimized.
16023 */
16024 VBOXSTRICTRC rcStrict;
16025 PCEMEXITREC pExitRec = NULL;
16026 if ( !fGstStepping
16027 && !fDbgStepping)
16028 pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16029 !fIOString
16030 ? !fIOWrite
16031 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_READ)
16032 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_WRITE)
16033 : !fIOWrite
16034 ? EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_READ)
16035 : EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_IO_PORT_STR_WRITE),
16036 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16037 if (!pExitRec)
16038 {
16039 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
16040 static uint32_t const s_aIOOpAnd[4] = { 0xff, 0xffff, 0, 0xffffffff }; /* AND masks for saving result in AL/AX/EAX. */
16041
16042 uint32_t const cbValue = s_aIOSizes[uIOSize];
16043 uint32_t const cbInstr = pVmxTransient->cbInstr;
16044 bool fUpdateRipAlready = false; /* ugly hack, should be temporary. */
16045 PVM pVM = pVCpu->CTX_SUFF(pVM);
16046 if (fIOString)
16047 {
16048 /*
16049 * INS/OUTS - I/O String instruction.
16050 *
16051 * Use instruction-information if available, otherwise fall back on
16052 * interpreting the instruction.
16053 */
16054 Log4Func(("cs:rip=%#04x:%#RX64 %#06x/%u %c str\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
16055 AssertReturn(pCtx->dx == uIOPort, VERR_VMX_IPE_2);
16056 bool const fInsOutsInfo = RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS);
16057 if (fInsOutsInfo)
16058 {
16059 int rc2 = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16060 AssertRCReturn(rc2, rc2);
16061 AssertReturn(pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize <= 2, VERR_VMX_IPE_3);
16062 AssertCompile(IEMMODE_16BIT == 0 && IEMMODE_32BIT == 1 && IEMMODE_64BIT == 2);
16063 IEMMODE const enmAddrMode = (IEMMODE)pVmxTransient->ExitInstrInfo.StrIo.u3AddrSize;
16064 bool const fRep = VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual);
16065 if (fIOWrite)
16066 rcStrict = IEMExecStringIoWrite(pVCpu, cbValue, enmAddrMode, fRep, cbInstr,
16067 pVmxTransient->ExitInstrInfo.StrIo.iSegReg, true /*fIoChecked*/);
16068 else
16069 {
16070 /*
16071 * The segment prefix for INS cannot be overridden and is always ES. We can safely assume X86_SREG_ES.
16072 * Hence "iSegReg" field is undefined in the instruction-information field in VT-x for INS.
16073 * See Intel Instruction spec. for "INS".
16074 * See Intel spec. Table 27-8 "Format of the VM-Exit Instruction-Information Field as Used for INS and OUTS".
16075 */
16076 rcStrict = IEMExecStringIoRead(pVCpu, cbValue, enmAddrMode, fRep, cbInstr, true /*fIoChecked*/);
16077 }
16078 }
16079 else
16080 rcStrict = IEMExecOne(pVCpu);
16081
16082 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
16083 fUpdateRipAlready = true;
16084 }
16085 else
16086 {
16087 /*
16088 * IN/OUT - I/O instruction.
16089 */
16090 Log4Func(("cs:rip=%04x:%08RX64 %#06x/%u %c\n", pCtx->cs.Sel, pCtx->rip, uIOPort, cbValue, fIOWrite ? 'w' : 'r'));
16091 uint32_t const uAndVal = s_aIOOpAnd[uIOSize];
16092 Assert(!VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual));
16093 if (fIOWrite)
16094 {
16095 rcStrict = IOMIOPortWrite(pVM, pVCpu, uIOPort, pCtx->eax & uAndVal, cbValue);
16096 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIOWrite);
16097 if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16098 && !pCtx->eflags.Bits.u1TF)
16099 rcStrict = EMRZSetPendingIoPortWrite(pVCpu, uIOPort, cbInstr, cbValue, pCtx->eax & uAndVal);
16100 }
16101 else
16102 {
16103 uint32_t u32Result = 0;
16104 rcStrict = IOMIOPortRead(pVM, pVCpu, uIOPort, &u32Result, cbValue);
16105 if (IOM_SUCCESS(rcStrict))
16106 {
16107 /* Save result of I/O IN instr. in AL/AX/EAX. */
16108 pCtx->eax = (pCtx->eax & ~uAndVal) | (u32Result & uAndVal);
16109 }
16110 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16111 && !pCtx->eflags.Bits.u1TF)
16112 rcStrict = EMRZSetPendingIoPortRead(pVCpu, uIOPort, cbInstr, cbValue);
16113 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitIORead);
16114 }
16115 }
16116
16117 if (IOM_SUCCESS(rcStrict))
16118 {
16119 if (!fUpdateRipAlready)
16120 {
16121 hmR0VmxAdvanceGuestRipBy(pVCpu, cbInstr);
16122 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP);
16123 }
16124
16125 /*
16126 * INS/OUTS with REP prefix updates RFLAGS, can be observed with triple-fault guru
16127 * while booting Fedora 17 64-bit guest.
16128 *
16129 * See Intel Instruction reference for REP/REPE/REPZ/REPNE/REPNZ.
16130 */
16131 if (fIOString)
16132 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RFLAGS);
16133
16134 /*
16135 * If any I/O breakpoints are armed, we need to check if one triggered
16136 * and take appropriate action.
16137 * Note that the I/O breakpoint type is undefined if CR4.DE is 0.
16138 */
16139 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_DR7);
16140 AssertRCReturn(rc, rc);
16141
16142 /** @todo Optimize away the DBGFBpIsHwIoArmed call by having DBGF tell the
16143 * execution engines about whether hyper BPs and such are pending. */
16144 uint32_t const uDr7 = pCtx->dr[7];
16145 if (RT_UNLIKELY( ( (uDr7 & X86_DR7_ENABLED_MASK)
16146 && X86_DR7_ANY_RW_IO(uDr7)
16147 && (pCtx->cr4 & X86_CR4_DE))
16148 || DBGFBpIsHwIoArmed(pVM)))
16149 {
16150 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxIoCheck);
16151
16152 /* We're playing with the host CPU state here, make sure we don't preempt or longjmp. */
16153 VMMRZCallRing3Disable(pVCpu);
16154 HM_DISABLE_PREEMPT(pVCpu);
16155
16156 bool fIsGuestDbgActive = CPUMR0DebugStateMaybeSaveGuest(pVCpu, true /* fDr6 */);
16157
16158 VBOXSTRICTRC rcStrict2 = DBGFBpCheckIo(pVM, pVCpu, pCtx, uIOPort, cbValue);
16159 if (rcStrict2 == VINF_EM_RAW_GUEST_TRAP)
16160 {
16161 /* Raise #DB. */
16162 if (fIsGuestDbgActive)
16163 ASMSetDR6(pCtx->dr[6]);
16164 if (pCtx->dr[7] != uDr7)
16165 pVCpu->hm.s.fCtxChanged |= HM_CHANGED_GUEST_DR7;
16166
16167 hmR0VmxSetPendingXcptDB(pVCpu);
16168 }
16169 /* rcStrict is VINF_SUCCESS, VINF_IOM_R3_IOPORT_COMMIT_WRITE, or in [VINF_EM_FIRST..VINF_EM_LAST],
16170 however we can ditch VINF_IOM_R3_IOPORT_COMMIT_WRITE as it has VMCPU_FF_IOM as backup. */
16171 else if ( rcStrict2 != VINF_SUCCESS
16172 && (rcStrict == VINF_SUCCESS || rcStrict2 < rcStrict))
16173 rcStrict = rcStrict2;
16174 AssertCompile(VINF_EM_LAST < VINF_IOM_R3_IOPORT_COMMIT_WRITE);
16175
16176 HM_RESTORE_PREEMPT();
16177 VMMRZCallRing3Enable(pVCpu);
16178 }
16179 }
16180
16181#ifdef VBOX_STRICT
16182 if ( rcStrict == VINF_IOM_R3_IOPORT_READ
16183 || rcStrict == VINF_EM_PENDING_R3_IOPORT_READ)
16184 Assert(!fIOWrite);
16185 else if ( rcStrict == VINF_IOM_R3_IOPORT_WRITE
16186 || rcStrict == VINF_IOM_R3_IOPORT_COMMIT_WRITE
16187 || rcStrict == VINF_EM_PENDING_R3_IOPORT_WRITE)
16188 Assert(fIOWrite);
16189 else
16190 {
16191# if 0 /** @todo r=bird: This is missing a bunch of VINF_EM_FIRST..VINF_EM_LAST
16192 * statuses, that the VMM device and some others may return. See
16193 * IOM_SUCCESS() for guidance. */
16194 AssertMsg( RT_FAILURE(rcStrict)
16195 || rcStrict == VINF_SUCCESS
16196 || rcStrict == VINF_EM_RAW_EMULATE_INSTR
16197 || rcStrict == VINF_EM_DBG_BREAKPOINT
16198 || rcStrict == VINF_EM_RAW_GUEST_TRAP
16199 || rcStrict == VINF_EM_RAW_TO_R3
16200 || rcStrict == VINF_TRPM_XCPT_DISPATCHED, ("%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16201# endif
16202 }
16203#endif
16204 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitIO, y1);
16205 }
16206 else
16207 {
16208 /*
16209 * Frequent exit or something needing probing. Get state and call EMHistoryExec.
16210 */
16211 int rc2 = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16212 AssertRCReturn(rc2, rc2);
16213 STAM_COUNTER_INC(!fIOString ? fIOWrite ? &pVCpu->hm.s.StatExitIOWrite : &pVCpu->hm.s.StatExitIORead
16214 : fIOWrite ? &pVCpu->hm.s.StatExitIOStringWrite : &pVCpu->hm.s.StatExitIOStringRead);
16215 Log4(("IOExit/%u: %04x:%08RX64: %s%s%s %#x LB %u -> EMHistoryExec\n",
16216 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16217 VMX_EXIT_QUAL_IO_IS_REP(pVmxTransient->uExitQual) ? "REP " : "",
16218 fIOWrite ? "OUT" : "IN", fIOString ? "S" : "", uIOPort, uIOSize));
16219
16220 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16221 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16222
16223 Log4(("IOExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16224 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16225 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16226 }
16227 return rcStrict;
16228}
16229
16230
16231/**
16232 * VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH). Unconditional
16233 * VM-exit.
16234 */
16235HMVMX_EXIT_DECL hmR0VmxExitTaskSwitch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16236{
16237 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16238
16239 /* Check if this task-switch occurred while delivery an event through the guest IDT. */
16240 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16241 AssertRCReturn(rc, rc);
16242 if (VMX_EXIT_QUAL_TASK_SWITCH_TYPE(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_TASK_SWITCH_TYPE_IDT)
16243 {
16244 rc = hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16245 AssertRCReturn(rc, rc);
16246 if (VMX_IDT_VECTORING_INFO_IS_VALID(pVmxTransient->uIdtVectoringInfo))
16247 {
16248 uint32_t uErrCode;
16249 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(pVmxTransient->uIdtVectoringInfo))
16250 {
16251 rc = hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16252 AssertRCReturn(rc, rc);
16253 uErrCode = pVmxTransient->uIdtVectoringErrorCode;
16254 }
16255 else
16256 uErrCode = 0;
16257
16258 RTGCUINTPTR GCPtrFaultAddress;
16259 if (VMX_IDT_VECTORING_INFO_IS_XCPT_PF(pVmxTransient->uIdtVectoringInfo))
16260 GCPtrFaultAddress = pVCpu->cpum.GstCtx.cr2;
16261 else
16262 GCPtrFaultAddress = 0;
16263
16264 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16265 AssertRCReturn(rc, rc);
16266
16267 hmR0VmxSetPendingEvent(pVCpu, VMX_ENTRY_INT_INFO_FROM_EXIT_IDT_INFO(pVmxTransient->uIdtVectoringInfo),
16268 pVmxTransient->cbInstr, uErrCode, GCPtrFaultAddress);
16269
16270 Log4Func(("Pending event. uIntType=%#x uVector=%#x\n", VMX_IDT_VECTORING_INFO_TYPE(pVmxTransient->uIdtVectoringInfo),
16271 VMX_IDT_VECTORING_INFO_VECTOR(pVmxTransient->uIdtVectoringInfo)));
16272 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16273 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16274 }
16275 }
16276
16277 /* Fall back to the interpreter to emulate the task-switch. */
16278 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitTaskSwitch);
16279 return VERR_EM_INTERPRETER;
16280}
16281
16282
16283/**
16284 * VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional VM-exit.
16285 */
16286HMVMX_EXIT_DECL hmR0VmxExitMtf(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16287{
16288 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16289
16290 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16291 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MONITOR_TRAP_FLAG;
16292 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16293 AssertRCReturn(rc, rc);
16294 return VINF_EM_DBG_STEPPED;
16295}
16296
16297
16298/**
16299 * VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional VM-exit.
16300 */
16301HMVMX_EXIT_DECL hmR0VmxExitApicAccess(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16302{
16303 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16304 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitApicAccess);
16305
16306 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16307 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16308 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16309 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16310 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16311 AssertRCReturn(rc, rc);
16312
16313 /*
16314 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16315 */
16316 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16317 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16318 {
16319 /* For some crazy guest, if an event delivery causes an APIC-access VM-exit, go to instruction emulation. */
16320 if (RT_UNLIKELY(pVCpu->hm.s.Event.fPending))
16321 {
16322 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16323 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16324 }
16325 }
16326 else
16327 {
16328 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16329 return rcStrict;
16330 }
16331
16332 /* IOMMIOPhysHandler() below may call into IEM, save the necessary state. */
16333 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16334 rc = hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16335 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16336 AssertRCReturn(rc, rc);
16337
16338 /* See Intel spec. 27-6 "Exit Qualifications for APIC-access VM-exits from Linear Accesses & Guest-Phyiscal Addresses" */
16339 uint32_t const uAccessType = VMX_EXIT_QUAL_APIC_ACCESS_TYPE(pVmxTransient->uExitQual);
16340 switch (uAccessType)
16341 {
16342 case VMX_APIC_ACCESS_TYPE_LINEAR_WRITE:
16343 case VMX_APIC_ACCESS_TYPE_LINEAR_READ:
16344 {
16345 AssertMsg( !(pVmcsInfo->u32ProcCtls & VMX_PROC_CTLS_USE_TPR_SHADOW)
16346 || VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual) != XAPIC_OFF_TPR,
16347 ("hmR0VmxExitApicAccess: can't access TPR offset while using TPR shadowing.\n"));
16348
16349 RTGCPHYS GCPhys = pVCpu->hm.s.vmx.u64GstMsrApicBase; /* Always up-to-date, as it is not part of the VMCS. */
16350 GCPhys &= PAGE_BASE_GC_MASK;
16351 GCPhys += VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual);
16352 Log4Func(("Linear access uAccessType=%#x GCPhys=%#RGp Off=%#x\n", uAccessType, GCPhys,
16353 VMX_EXIT_QUAL_APIC_ACCESS_OFFSET(pVmxTransient->uExitQual)));
16354
16355 PVM pVM = pVCpu->CTX_SUFF(pVM);
16356 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16357 rcStrict = IOMMMIOPhysHandler(pVM, pVCpu,
16358 uAccessType == VMX_APIC_ACCESS_TYPE_LINEAR_READ ? 0 : X86_TRAP_PF_RW,
16359 CPUMCTX2CORE(pCtx), GCPhys);
16360 Log4Func(("IOMMMIOPhysHandler returned %Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16361 if ( rcStrict == VINF_SUCCESS
16362 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16363 || rcStrict == VERR_PAGE_NOT_PRESENT)
16364 {
16365 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16366 | HM_CHANGED_GUEST_APIC_TPR);
16367 rcStrict = VINF_SUCCESS;
16368 }
16369 break;
16370 }
16371
16372 default:
16373 {
16374 Log4Func(("uAccessType=%#x\n", uAccessType));
16375 rcStrict = VINF_EM_RAW_EMULATE_INSTR;
16376 break;
16377 }
16378 }
16379
16380 if (rcStrict != VINF_SUCCESS)
16381 STAM_COUNTER_INC(&pVCpu->hm.s.StatSwitchApicAccessToR3);
16382 return rcStrict;
16383}
16384
16385
16386/**
16387 * VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX). Conditional
16388 * VM-exit.
16389 */
16390HMVMX_EXIT_DECL hmR0VmxExitMovDRx(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16391{
16392 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16393
16394 /* We should -not- get this VM-exit if the guest's debug registers were active. */
16395 if (pVmxTransient->fWasGuestDebugStateActive)
16396 {
16397 AssertMsgFailed(("Unexpected MOV DRx exit\n"));
16398 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, pVmxTransient->uExitReason);
16399 }
16400
16401 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16402 if ( !pVCpu->hm.s.fSingleInstruction
16403 && !pVmxTransient->fWasHyperDebugStateActive)
16404 {
16405 Assert(!DBGFIsStepping(pVCpu));
16406 Assert(pVmcsInfo->u32XcptBitmap & RT_BIT(X86_XCPT_DB));
16407
16408 /* Don't intercept MOV DRx any more. */
16409 pVmcsInfo->u32ProcCtls &= ~VMX_PROC_CTLS_MOV_DR_EXIT;
16410 int rc = VMXWriteVmcs32(VMX_VMCS32_CTRL_PROC_EXEC, pVmcsInfo->u32ProcCtls);
16411 AssertRCReturn(rc, rc);
16412
16413 /* We're playing with the host CPU state here, make sure we can't preempt or longjmp. */
16414 VMMRZCallRing3Disable(pVCpu);
16415 HM_DISABLE_PREEMPT(pVCpu);
16416
16417 /* Save the host & load the guest debug state, restart execution of the MOV DRx instruction. */
16418 CPUMR0LoadGuestDebugState(pVCpu, true /* include DR6 */);
16419 Assert(CPUMIsGuestDebugStateActive(pVCpu) || HC_ARCH_BITS == 32);
16420
16421 HM_RESTORE_PREEMPT();
16422 VMMRZCallRing3Enable(pVCpu);
16423
16424#ifdef VBOX_WITH_STATISTICS
16425 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16426 AssertRCReturn(rc, rc);
16427 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16428 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16429 else
16430 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16431#endif
16432 STAM_COUNTER_INC(&pVCpu->hm.s.StatDRxContextSwitch);
16433 return VINF_SUCCESS;
16434 }
16435
16436 /*
16437 * EMInterpretDRx[Write|Read]() calls CPUMIsGuestIn64BitCode() which requires EFER MSR, CS.
16438 * The EFER MSR is always up-to-date.
16439 * Update the segment registers and DR7 from the CPU.
16440 */
16441 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16442 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16443 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, CPUMCTX_EXTRN_SREG_MASK | CPUMCTX_EXTRN_DR7);
16444 AssertRCReturn(rc, rc);
16445 Log4Func(("cs:rip=%#04x:%#RX64\n", pCtx->cs.Sel, pCtx->rip));
16446
16447 PVM pVM = pVCpu->CTX_SUFF(pVM);
16448 if (VMX_EXIT_QUAL_DRX_DIRECTION(pVmxTransient->uExitQual) == VMX_EXIT_QUAL_DRX_DIRECTION_WRITE)
16449 {
16450 rc = EMInterpretDRxWrite(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16451 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual),
16452 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual));
16453 if (RT_SUCCESS(rc))
16454 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_DR7);
16455 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxWrite);
16456 }
16457 else
16458 {
16459 rc = EMInterpretDRxRead(pVM, pVCpu, CPUMCTX2CORE(pCtx),
16460 VMX_EXIT_QUAL_DRX_GENREG(pVmxTransient->uExitQual),
16461 VMX_EXIT_QUAL_DRX_REGISTER(pVmxTransient->uExitQual));
16462 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitDRxRead);
16463 }
16464
16465 Assert(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER);
16466 if (RT_SUCCESS(rc))
16467 {
16468 int rc2 = hmR0VmxAdvanceGuestRip(pVCpu, pVmxTransient);
16469 AssertRCReturn(rc2, rc2);
16470 return VINF_SUCCESS;
16471 }
16472 return rc;
16473}
16474
16475
16476/**
16477 * VM-exit handler for EPT misconfiguration (VMX_EXIT_EPT_MISCONFIG).
16478 * Conditional VM-exit.
16479 */
16480HMVMX_EXIT_DECL hmR0VmxExitEptMisconfig(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16481{
16482 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16483 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16484
16485 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16486 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16487 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16488 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16489 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16490 AssertRCReturn(rc, rc);
16491
16492 /*
16493 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16494 */
16495 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16496 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16497 {
16498 /*
16499 * In the unlikely case where delivering an event causes an EPT misconfig (MMIO), go back to
16500 * instruction emulation to inject the original event. Otherwise, injecting the original event
16501 * using hardware-assisted VMX would would trigger the same EPT misconfig VM-exit again.
16502 */
16503 if (!pVCpu->hm.s.Event.fPending)
16504 { /* likely */ }
16505 else
16506 {
16507 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectInterpret);
16508#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16509 /** @todo NSTVMX: Think about how this should be handled. */
16510 if (pVmxTransient->fIsNestedGuest)
16511 return VERR_VMX_IPE_3;
16512#endif
16513 return VINF_EM_RAW_INJECT_TRPM_EVENT;
16514 }
16515 }
16516 else
16517 {
16518 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16519 return rcStrict;
16520 }
16521
16522 /*
16523 * Get sufficent state and update the exit history entry.
16524 */
16525 RTGCPHYS GCPhys;
16526 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16527 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16528 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16529 AssertRCReturn(rc, rc);
16530
16531 PCEMEXITREC pExitRec = EMHistoryUpdateFlagsAndTypeAndPC(pVCpu,
16532 EMEXIT_MAKE_FT(EMEXIT_F_KIND_EM | EMEXIT_F_HM, EMEXITTYPE_MMIO),
16533 pVCpu->cpum.GstCtx.rip + pVCpu->cpum.GstCtx.cs.u64Base);
16534 if (!pExitRec)
16535 {
16536 /*
16537 * If we succeed, resume guest execution.
16538 * If we fail in interpreting the instruction because we couldn't get the guest physical address
16539 * of the page containing the instruction via the guest's page tables (we would invalidate the guest page
16540 * in the host TLB), resume execution which would cause a guest page fault to let the guest handle this
16541 * weird case. See @bugref{6043}.
16542 */
16543 PVM pVM = pVCpu->CTX_SUFF(pVM);
16544 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16545 rcStrict = PGMR0Trap0eHandlerNPMisconfig(pVM, pVCpu, PGMMODE_EPT, CPUMCTX2CORE(pCtx), GCPhys, UINT32_MAX);
16546 Log4Func(("At %#RGp RIP=%#RX64 rc=%Rrc\n", GCPhys, pCtx->rip, VBOXSTRICTRC_VAL(rcStrict)));
16547 if ( rcStrict == VINF_SUCCESS
16548 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16549 || rcStrict == VERR_PAGE_NOT_PRESENT)
16550 {
16551 /* Successfully handled MMIO operation. */
16552 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS
16553 | HM_CHANGED_GUEST_APIC_TPR);
16554 rcStrict = VINF_SUCCESS;
16555 }
16556 }
16557 else
16558 {
16559 /*
16560 * Frequent exit or something needing probing. Call EMHistoryExec.
16561 */
16562 Log4(("EptMisscfgExit/%u: %04x:%08RX64: %RGp -> EMHistoryExec\n",
16563 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip, GCPhys));
16564
16565 rcStrict = EMHistoryExec(pVCpu, pExitRec, 0);
16566 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16567
16568 Log4(("EptMisscfgExit/%u: %04x:%08RX64: EMHistoryExec -> %Rrc + %04x:%08RX64\n",
16569 pVCpu->idCpu, pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip,
16570 VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cs.Sel, pVCpu->cpum.GstCtx.rip));
16571 }
16572 return rcStrict;
16573}
16574
16575
16576/**
16577 * VM-exit handler for EPT violation (VMX_EXIT_EPT_VIOLATION). Conditional
16578 * VM-exit.
16579 */
16580HMVMX_EXIT_DECL hmR0VmxExitEptViolation(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16581{
16582 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16583 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
16584
16585 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
16586 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
16587 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16588 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
16589 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
16590 AssertRCReturn(rc, rc);
16591
16592 /*
16593 * If this VM-exit occurred while delivering an event through the guest IDT, handle it accordingly.
16594 */
16595 VBOXSTRICTRC rcStrict = hmR0VmxCheckExitDueToEventDelivery(pVCpu, pVmxTransient);
16596 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16597 {
16598 /*
16599 * If delivery of an event causes an EPT violation (true nested #PF and not MMIO),
16600 * we shall resolve the nested #PF and re-inject the original event.
16601 */
16602 if (pVCpu->hm.s.Event.fPending)
16603 STAM_COUNTER_INC(&pVCpu->hm.s.StatInjectReflectNPF);
16604 }
16605 else
16606 {
16607 Assert(rcStrict != VINF_HM_DOUBLE_FAULT);
16608 return rcStrict;
16609 }
16610
16611 RTGCPHYS GCPhys;
16612 PVMXVMCSINFO pVmcsInfo = pVmxTransient->pVmcsInfo;
16613 rc = VMXReadVmcs64(VMX_VMCS64_RO_GUEST_PHYS_ADDR_FULL, &GCPhys);
16614 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16615 rc |= hmR0VmxImportGuestState(pVCpu, pVmcsInfo, IEM_CPUMCTX_EXTRN_MUST_MASK);
16616 AssertRCReturn(rc, rc);
16617
16618 /* Intel spec. Table 27-7 "Exit Qualifications for EPT violations". */
16619 AssertMsg(((pVmxTransient->uExitQual >> 7) & 3) != 2, ("%#RX64", pVmxTransient->uExitQual));
16620
16621 RTGCUINT uErrorCode = 0;
16622 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_INSTR_FETCH)
16623 uErrorCode |= X86_TRAP_PF_ID;
16624 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_DATA_WRITE)
16625 uErrorCode |= X86_TRAP_PF_RW;
16626 if (pVmxTransient->uExitQual & VMX_EXIT_QUAL_EPT_ENTRY_PRESENT)
16627 uErrorCode |= X86_TRAP_PF_P;
16628
16629 TRPMAssertXcptPF(pVCpu, GCPhys, uErrorCode);
16630
16631 /* Handle the pagefault trap for the nested shadow table. */
16632 PVM pVM = pVCpu->CTX_SUFF(pVM);
16633 PCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
16634
16635 Log4Func(("EPT violation %#x at %#RX64 ErrorCode %#x cs:rip=%#04x:%#RX64\n", pVmxTransient->uExitQual, GCPhys, uErrorCode,
16636 pCtx->cs.Sel, pCtx->rip));
16637
16638 rcStrict = PGMR0Trap0eHandlerNestedPaging(pVM, pVCpu, PGMMODE_EPT, uErrorCode, CPUMCTX2CORE(pCtx), GCPhys);
16639 TRPMResetTrap(pVCpu);
16640
16641 /* Same case as PGMR0Trap0eHandlerNPMisconfig(). See comment above, @bugref{6043}. */
16642 if ( rcStrict == VINF_SUCCESS
16643 || rcStrict == VERR_PAGE_TABLE_NOT_PRESENT
16644 || rcStrict == VERR_PAGE_NOT_PRESENT)
16645 {
16646 /* Successfully synced our nested page tables. */
16647 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitReasonNpf);
16648 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RSP | HM_CHANGED_GUEST_RFLAGS);
16649 return VINF_SUCCESS;
16650 }
16651
16652 Log4Func(("EPT return to ring-3 rcStrict2=%Rrc\n", VBOXSTRICTRC_VAL(rcStrict)));
16653 return rcStrict;
16654}
16655
16656
16657#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
16658/**
16659 * VM-exit handler for VMCLEAR (VMX_EXIT_VMCLEAR). Unconditional VM-exit.
16660 */
16661HMVMX_EXIT_DECL hmR0VmxExitVmclear(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16662{
16663 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16664
16665 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16666 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16667 | CPUMCTX_EXTRN_HWVIRT
16668 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16669 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16670 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16671 AssertRCReturn(rc, rc);
16672
16673 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16674
16675 VMXVEXITINFO ExitInfo;
16676 RT_ZERO(ExitInfo);
16677 ExitInfo.uReason = pVmxTransient->uExitReason;
16678 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16679 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16680 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16681 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16682
16683 VBOXSTRICTRC rcStrict = IEMExecDecodedVmclear(pVCpu, &ExitInfo);
16684 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16685 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16686 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16687 {
16688 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16689 rcStrict = VINF_SUCCESS;
16690 }
16691 return rcStrict;
16692}
16693
16694
16695/**
16696 * VM-exit handler for VMLAUNCH (VMX_EXIT_VMLAUNCH). Unconditional VM-exit.
16697 */
16698HMVMX_EXIT_DECL hmR0VmxExitVmlaunch(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16699{
16700 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16701
16702 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMLAUNCH,
16703 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16704 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16705 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16706 AssertRCReturn(rc, rc);
16707
16708 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16709
16710 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16711 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMLAUNCH);
16712 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16713 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16714 {
16715 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16716 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16717 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16718 }
16719 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16720 return rcStrict;
16721}
16722
16723
16724/**
16725 * VM-exit handler for VMPTRLD (VMX_EXIT_VMPTRLD). Unconditional VM-exit.
16726 */
16727HMVMX_EXIT_DECL hmR0VmxExitVmptrld(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16728{
16729 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16730
16731 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16732 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16733 | CPUMCTX_EXTRN_HWVIRT
16734 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16735 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16736 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16737 AssertRCReturn(rc, rc);
16738
16739 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16740
16741 VMXVEXITINFO ExitInfo;
16742 RT_ZERO(ExitInfo);
16743 ExitInfo.uReason = pVmxTransient->uExitReason;
16744 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16745 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16746 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16747 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16748
16749 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrld(pVCpu, &ExitInfo);
16750 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16751 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16752 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16753 {
16754 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16755 rcStrict = VINF_SUCCESS;
16756 }
16757 return rcStrict;
16758}
16759
16760
16761/**
16762 * VM-exit handler for VMPTRST (VMX_EXIT_VMPTRST). Unconditional VM-exit.
16763 */
16764HMVMX_EXIT_DECL hmR0VmxExitVmptrst(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16765{
16766 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16767
16768 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16769 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16770 | CPUMCTX_EXTRN_HWVIRT
16771 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16772 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16773 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16774 AssertRCReturn(rc, rc);
16775
16776 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16777
16778 VMXVEXITINFO ExitInfo;
16779 RT_ZERO(ExitInfo);
16780 ExitInfo.uReason = pVmxTransient->uExitReason;
16781 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16782 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16783 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16784 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16785
16786 VBOXSTRICTRC rcStrict = IEMExecDecodedVmptrst(pVCpu, &ExitInfo);
16787 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16788 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16789 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16790 {
16791 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16792 rcStrict = VINF_SUCCESS;
16793 }
16794 return rcStrict;
16795}
16796
16797
16798/**
16799 * VM-exit handler for VMREAD (VMX_EXIT_VMREAD). Conditional VM-exit.
16800 */
16801HMVMX_EXIT_DECL hmR0VmxExitVmread(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16802{
16803 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16804
16805 /*
16806 * Strictly speaking we should not get VMREAD VM-exits for shadow VMCS fields and
16807 * thus might not need to import the shadow VMCS state, it's safer just in case
16808 * code elsewhere dares look at unsynced VMCS fields.
16809 */
16810 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16811 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16812 | CPUMCTX_EXTRN_HWVIRT
16813 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16814 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16815 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16816 AssertRCReturn(rc, rc);
16817
16818 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16819
16820 VMXVEXITINFO ExitInfo;
16821 RT_ZERO(ExitInfo);
16822 ExitInfo.uReason = pVmxTransient->uExitReason;
16823 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16824 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16825 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16826 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16827 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_WRITE, &ExitInfo.GCPtrEffAddr);
16828
16829 VBOXSTRICTRC rcStrict = IEMExecDecodedVmread(pVCpu, &ExitInfo);
16830 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16831 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
16832 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16833 {
16834 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16835 rcStrict = VINF_SUCCESS;
16836 }
16837 return rcStrict;
16838}
16839
16840
16841/**
16842 * VM-exit handler for VMRESUME (VMX_EXIT_VMRESUME). Unconditional VM-exit.
16843 */
16844HMVMX_EXIT_DECL hmR0VmxExitVmresume(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16845{
16846 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16847
16848 /* Import the entire VMCS state for now as we would be switching VMCS on successful VMRESUME,
16849 otherwise we could import just IEM_CPUMCTX_EXTRN_VMX_VMENTRY_MASK. */
16850 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16851 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, HMVMX_CPUMCTX_EXTRN_ALL);
16852 AssertRCReturn(rc, rc);
16853
16854 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16855
16856 STAM_PROFILE_ADV_START(&pVCpu->hm.s.StatExitVmentry, z);
16857 VBOXSTRICTRC rcStrict = IEMExecDecodedVmlaunchVmresume(pVCpu, pVmxTransient->cbInstr, VMXINSTRID_VMRESUME);
16858 STAM_PROFILE_ADV_STOP(&pVCpu->hm.s.StatExitVmentry, z);
16859 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16860 {
16861 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_ALL_GUEST);
16862 if (CPUMIsGuestInVmxNonRootMode(&pVCpu->cpum.GstCtx))
16863 rcStrict = VINF_VMX_VMLAUNCH_VMRESUME;
16864 }
16865 Assert(rcStrict != VINF_IEM_RAISED_XCPT);
16866 return rcStrict;
16867}
16868
16869
16870/**
16871 * VM-exit handler for VMWRITE (VMX_EXIT_VMWRITE). Conditional VM-exit.
16872 */
16873HMVMX_EXIT_DECL hmR0VmxExitVmwrite(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16874{
16875 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16876
16877 /*
16878 * Although we should not get VMWRITE VM-exits for shadow VMCS fields, since our HM hook
16879 * gets invoked when IEM's VMWRITE instruction emulation modifies the current VMCS and it
16880 * flags re-loading the entire shadow VMCS, we should save the entire shadow VMCS here.
16881 */
16882 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16883 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16884 | CPUMCTX_EXTRN_HWVIRT
16885 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16886 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16887 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16888 AssertRCReturn(rc, rc);
16889
16890 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16891
16892 VMXVEXITINFO ExitInfo;
16893 RT_ZERO(ExitInfo);
16894 ExitInfo.uReason = pVmxTransient->uExitReason;
16895 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16896 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16897 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16898 if (!ExitInfo.InstrInfo.VmreadVmwrite.fIsRegOperand)
16899 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16900
16901 VBOXSTRICTRC rcStrict = IEMExecDecodedVmwrite(pVCpu, &ExitInfo);
16902 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16903 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16904 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16905 {
16906 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16907 rcStrict = VINF_SUCCESS;
16908 }
16909 return rcStrict;
16910}
16911
16912
16913/**
16914 * VM-exit handler for VMXOFF (VMX_EXIT_VMXOFF). Unconditional VM-exit.
16915 */
16916HMVMX_EXIT_DECL hmR0VmxExitVmxoff(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16917{
16918 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16919
16920 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16921 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_CR4
16922 | CPUMCTX_EXTRN_HWVIRT
16923 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_NO_MEM_MASK);
16924 AssertRCReturn(rc, rc);
16925
16926 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16927
16928 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxoff(pVCpu, pVmxTransient->cbInstr);
16929 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16930 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_HWVIRT);
16931 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16932 {
16933 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16934 rcStrict = VINF_SUCCESS;
16935 }
16936 return rcStrict;
16937}
16938
16939
16940/**
16941 * VM-exit handler for VMXON (VMX_EXIT_VMXON). Unconditional VM-exit.
16942 */
16943HMVMX_EXIT_DECL hmR0VmxExitVmxon(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16944{
16945 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16946
16947 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16948 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16949 | CPUMCTX_EXTRN_HWVIRT
16950 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16951 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16952 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16953 AssertRCReturn(rc, rc);
16954
16955 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16956
16957 VMXVEXITINFO ExitInfo;
16958 RT_ZERO(ExitInfo);
16959 ExitInfo.uReason = pVmxTransient->uExitReason;
16960 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16961 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16962 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16963 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
16964
16965 VBOXSTRICTRC rcStrict = IEMExecDecodedVmxon(pVCpu, &ExitInfo);
16966 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
16967 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS | HM_CHANGED_GUEST_HWVIRT);
16968 else if (rcStrict == VINF_IEM_RAISED_XCPT)
16969 {
16970 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
16971 rcStrict = VINF_SUCCESS;
16972 }
16973 return rcStrict;
16974}
16975
16976
16977/**
16978 * VM-exit handler for INVVPID (VMX_EXIT_INVVPID). Unconditional VM-exit.
16979 */
16980HMVMX_EXIT_DECL hmR0VmxExitInvvpid(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
16981{
16982 HMVMX_VALIDATE_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
16983
16984 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
16985 rc |= hmR0VmxImportGuestState(pVCpu, pVmxTransient->pVmcsInfo, CPUMCTX_EXTRN_RSP | CPUMCTX_EXTRN_SREG_MASK
16986 | IEM_CPUMCTX_EXTRN_EXEC_DECODED_MEM_MASK);
16987 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
16988 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
16989 AssertRCReturn(rc, rc);
16990
16991 HMVMX_CHECK_EXIT_DUE_TO_VMX_INSTR(pVCpu, pVmxTransient->uExitReason);
16992
16993 VMXVEXITINFO ExitInfo;
16994 RT_ZERO(ExitInfo);
16995 ExitInfo.uReason = pVmxTransient->uExitReason;
16996 ExitInfo.u64Qual = pVmxTransient->uExitQual;
16997 ExitInfo.InstrInfo.u = pVmxTransient->ExitInstrInfo.u;
16998 ExitInfo.cbInstr = pVmxTransient->cbInstr;
16999 HMVMX_DECODE_MEM_OPERAND(pVCpu, ExitInfo.InstrInfo.u, ExitInfo.u64Qual, VMXMEMACCESS_READ, &ExitInfo.GCPtrEffAddr);
17000
17001 VBOXSTRICTRC rcStrict = IEMExecDecodedInvvpid(pVCpu, &ExitInfo);
17002 if (RT_LIKELY(rcStrict == VINF_SUCCESS))
17003 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_GUEST_RIP | HM_CHANGED_GUEST_RFLAGS);
17004 else if (rcStrict == VINF_IEM_RAISED_XCPT)
17005 {
17006 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17007 rcStrict = VINF_SUCCESS;
17008 }
17009 return rcStrict;
17010}
17011#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17012/** @} */
17013
17014
17015#ifdef VBOX_WITH_NESTED_HWVIRT_VMX
17016/** @name Nested-guest VM-exit handlers.
17017 * @{
17018 */
17019/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
17020/* -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=- Nested-guest VM-exit handlers -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
17021/* -=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=--=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= */
17022
17023/**
17024 * Nested-guest VM-exit handler for exceptions or NMIs (VMX_EXIT_XCPT_OR_NMI).
17025 * Conditional VM-exit.
17026 */
17027HMVMX_EXIT_DECL hmR0VmxExitXcptOrNmiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17028{
17029 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17030
17031 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
17032 AssertRCReturn(rc, rc);
17033
17034 uint64_t const uExitIntInfo = pVmxTransient->uExitIntInfo;
17035 uint32_t const uExitIntType = VMX_EXIT_INT_INFO_TYPE(uExitIntInfo);
17036 Assert(VMX_EXIT_INT_INFO_IS_VALID(uExitIntInfo));
17037
17038 switch (uExitIntType)
17039 {
17040 /*
17041 * Physical NMIs:
17042 * We shouldn't direct host physical NMIs to the nested-guest. Dispatch it to the host.
17043 */
17044 case VMX_EXIT_INT_INFO_TYPE_NMI:
17045 return hmR0VmxExitHostNmi(pVCpu, pVmxTransient->pVmcsInfo);
17046
17047 /*
17048 * Hardware exceptions,
17049 * Software exceptions,
17050 * Privileged software exceptions:
17051 * Figure out if the exception must be delivered to the guest or the nested-guest.
17052 */
17053 case VMX_EXIT_INT_INFO_TYPE_SW_XCPT:
17054 case VMX_EXIT_INT_INFO_TYPE_PRIV_SW_XCPT:
17055 case VMX_EXIT_INT_INFO_TYPE_HW_XCPT:
17056 {
17057 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
17058 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17059 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17060 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17061 AssertRCReturn(rc, rc);
17062
17063 /*
17064 * If this VM-exit occurred while delivering an event through the nested-guest IDT, handle it accordingly.
17065 */
17066 rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
17067 AssertRCReturn(rc, rc);
17068
17069 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs. */
17070 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
17071
17072 uint8_t const uVector = VMX_EXIT_INT_INFO_VECTOR(uExitIntInfo);
17073 bool const fIntercept = CPUMIsGuestVmxXcptInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uVector,
17074 pVmxTransient->uExitIntErrorCode);
17075 if (fIntercept)
17076 {
17077 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17078 AssertRCReturn(rc, rc);
17079
17080 /*
17081 * For VM-exits due to software exceptions (those generated by INT3 or INTO) and privileged
17082 * software exceptions (those generated by INT1/ICEBP) we need to supply the VM-exit instruction
17083 * length. However, if delivery of a software interrupt, software exception or privileged
17084 * software exception causes a VM-exit, that too provides the VM-exit instruction length.
17085 */
17086 VMXVEXITINFO ExitInfo;
17087 RT_ZERO(ExitInfo);
17088 ExitInfo.uReason = pVmxTransient->uExitReason;
17089 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17090 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17091
17092 VMXVEXITEVENTINFO ExitEventInfo;
17093 RT_ZERO(ExitEventInfo);
17094 ExitEventInfo.uExitIntInfo = pVmxTransient->uExitIntInfo;
17095 ExitEventInfo.uExitIntErrCode = pVmxTransient->uExitIntErrorCode;
17096 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17097 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17098 if (pVCpu->hm.s.Event.fPending)
17099 {
17100 Assert(ExitEventInfo.uIdtVectoringInfo == pVCpu->hm.s.Event.u64IntInfo);
17101 if (VMX_IDT_VECTORING_INFO_IS_ERROR_CODE_VALID(ExitEventInfo.uIdtVectoringInfo))
17102 Assert(ExitEventInfo.uIdtVectoringErrCode == pVCpu->hm.s.Event.u32ErrCode);
17103 if ( VMX_IDT_VECTORING_INFO_TYPE(ExitEventInfo.uIdtVectoringInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_INT
17104 || VMX_IDT_VECTORING_INFO_TYPE(ExitEventInfo.uIdtVectoringInfo) == VMX_IDT_VECTORING_INFO_TYPE_PRIV_SW_XCPT
17105 || VMX_IDT_VECTORING_INFO_TYPE(ExitEventInfo.uIdtVectoringInfo) == VMX_IDT_VECTORING_INFO_TYPE_SW_XCPT)
17106 Assert(ExitInfo.cbInstr == pVCpu->hm.s.Event.cbInstr);
17107
17108 pVCpu->hm.s.Event.fPending = false;
17109 }
17110 return IEMExecVmxVmexitXcpt(pVCpu, &ExitInfo, &ExitEventInfo);
17111 }
17112
17113 /* Nested paging is currently a requirement, otherwise we would need to handle shadow #PFs. */
17114 Assert(pVCpu->CTX_SUFF(pVM)->hm.s.fNestedPaging);
17115
17116 /*
17117 * If the guest hypervisor is not intercepting an exception that caused a VM-exit directly,
17118 * forward it to the guest (for e.g, an instruction raises a #GP that causes this VM-exit
17119 * despite the guest hypervisor not intercept #GPs, inject #GP into the nested-guest).
17120 *
17121 * If the guest hypervisor is not intercepting an exception that caused a VM-exit indirectly,
17122 * inject the secondary exception into the nested-guest (for e.g, an instruction raises a #GP,
17123 * delivery of which causes an #AC. We get a #AC VM-exit but the guest-hypervisor is not
17124 * intercepting #AC, then inject the #AC into the nested-guest rather than the original #GP).
17125 */
17126 pVCpu->hm.s.Event.fPending = false;
17127 return hmR0VmxExitXcptAll(pVCpu, pVmxTransient, uVector);
17128 }
17129
17130 /*
17131 * Software interrupts:
17132 * VM-exits cannot be caused by software interrupts.
17133 *
17134 * External interrupts:
17135 * This should only happen when "acknowledge external interrupts on VM-exit"
17136 * control is set. However, we never set this when executing a guest or
17137 * nested-guest. For nested-guests it is emulated while injecting interrupts into
17138 * the guest.
17139 */
17140 case VMX_EXIT_INT_INFO_TYPE_SW_INT:
17141 case VMX_EXIT_INT_INFO_TYPE_EXT_INT:
17142 default:
17143 {
17144 pVCpu->hm.s.u32HMError = pVmxTransient->uExitIntInfo;
17145 return VERR_VMX_UNEXPECTED_INTERRUPTION_EXIT_TYPE;
17146 }
17147 }
17148}
17149
17150
17151/**
17152 * Nested-guest VM-exit handler for triple faults (VMX_EXIT_TRIPLE_FAULT).
17153 * Unconditional VM-exit.
17154 */
17155HMVMX_EXIT_DECL hmR0VmxExitTripleFaultNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17156{
17157 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17158 return IEMExecVmxVmexitTripleFault(pVCpu);
17159}
17160
17161
17162/**
17163 * Nested-guest VM-exit handler for interrupt-window exiting (VMX_EXIT_INT_WINDOW).
17164 */
17165HMVMX_EXIT_NSRC_DECL hmR0VmxExitIntWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17166{
17167 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17168
17169 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INT_WINDOW_EXIT))
17170 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17171 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17172}
17173
17174
17175/**
17176 * Nested-guest VM-exit handler for NMI-window exiting (VMX_EXIT_NMI_WINDOW).
17177 */
17178HMVMX_EXIT_NSRC_DECL hmR0VmxExitNmiWindowNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17179{
17180 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17181
17182 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_NMI_WINDOW_EXIT))
17183 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17184 return hmR0VmxExitIntWindow(pVCpu, pVmxTransient);
17185}
17186
17187
17188/**
17189 * Nested-guest VM-exit handler for task switches (VMX_EXIT_TASK_SWITCH).
17190 * Unconditional VM-exit.
17191 */
17192HMVMX_EXIT_DECL hmR0VmxExitTaskSwitchNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17193{
17194 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17195
17196 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17197 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17198 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17199 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17200 AssertRCReturn(rc, rc);
17201
17202 VMXVEXITINFO ExitInfo;
17203 RT_ZERO(ExitInfo);
17204 ExitInfo.uReason = pVmxTransient->uExitReason;
17205 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17206 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17207
17208 VMXVEXITEVENTINFO ExitEventInfo;
17209 RT_ZERO(ExitEventInfo);
17210 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17211 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17212 return IEMExecVmxVmexitTaskSwitch(pVCpu, &ExitInfo, &ExitEventInfo);
17213}
17214
17215
17216/**
17217 * Nested-guest VM-exit handler for HLT (VMX_EXIT_HLT). Conditional VM-exit.
17218 */
17219HMVMX_EXIT_DECL hmR0VmxExitHltNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17220{
17221 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17222
17223 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_HLT_EXIT))
17224 {
17225 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17226 AssertRCReturn(rc, rc);
17227 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17228 }
17229 return hmR0VmxExitHlt(pVCpu, pVmxTransient);
17230}
17231
17232
17233/**
17234 * Nested-guest VM-exit handler for INVLPG (VMX_EXIT_INVLPG). Conditional VM-exit.
17235 */
17236HMVMX_EXIT_DECL hmR0VmxExitInvlpgNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17237{
17238 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17239
17240 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17241 {
17242 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17243 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17244 AssertRCReturn(rc, rc);
17245
17246 VMXVEXITINFO ExitInfo;
17247 RT_ZERO(ExitInfo);
17248 ExitInfo.uReason = pVmxTransient->uExitReason;
17249 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17250 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17251 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17252 }
17253 return hmR0VmxExitInvlpg(pVCpu, pVmxTransient);
17254}
17255
17256
17257/**
17258 * Nested-guest VM-exit handler for RDPMC (VMX_EXIT_RDPMC). Conditional VM-exit.
17259 */
17260HMVMX_EXIT_DECL hmR0VmxExitRdpmcNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17261{
17262 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17263
17264 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDPMC_EXIT))
17265 {
17266 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17267 AssertRCReturn(rc, rc);
17268 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17269 }
17270 return hmR0VmxExitRdpmc(pVCpu, pVmxTransient);
17271}
17272
17273
17274/**
17275 * Nested-guest VM-exit handler for VMREAD (VMX_EXIT_VMREAD) and VMWRITE
17276 * (VMX_EXIT_VMWRITE). Conditional VM-exit.
17277 */
17278HMVMX_EXIT_DECL hmR0VmxExitVmreadVmwriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17279{
17280 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17281
17282 Assert( pVmxTransient->uExitReason == VMX_EXIT_VMREAD
17283 || pVmxTransient->uExitReason == VMX_EXIT_VMWRITE);
17284
17285 int rc = hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17286 AssertRCReturn(rc, rc);
17287
17288 uint8_t const iGReg = pVmxTransient->ExitInstrInfo.VmreadVmwrite.iReg2;
17289 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17290 uint64_t u64VmcsField = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17291
17292 HMVMX_CPUMCTX_ASSERT(pVCpu, CPUMCTX_EXTRN_EFER);
17293 if (!CPUMIsGuestInLongModeEx(&pVCpu->cpum.GstCtx))
17294 u64VmcsField &= UINT64_C(0xffffffff);
17295
17296 if (CPUMIsGuestVmxVmreadVmwriteInterceptSet(pVCpu, pVmxTransient->uExitReason, u64VmcsField))
17297 {
17298 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17299 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17300 AssertRCReturn(rc, rc);
17301
17302 VMXVEXITINFO ExitInfo;
17303 RT_ZERO(ExitInfo);
17304 ExitInfo.uReason = pVmxTransient->uExitReason;
17305 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17306 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17307 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17308 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17309 }
17310
17311 if (pVmxTransient->uExitReason == VMX_EXIT_VMREAD)
17312 return hmR0VmxExitVmread(pVCpu, pVmxTransient);
17313 return hmR0VmxExitVmwrite(pVCpu, pVmxTransient);
17314}
17315
17316
17317/**
17318 * Nested-guest VM-exit handler for RDTSC (VMX_EXIT_RDTSC). Conditional VM-exit.
17319 */
17320HMVMX_EXIT_DECL hmR0VmxExitRdtscNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17321{
17322 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17323
17324 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17325 {
17326 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17327 AssertRCReturn(rc, rc);
17328 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17329 }
17330
17331 return hmR0VmxExitRdtsc(pVCpu, pVmxTransient);
17332}
17333
17334
17335/**
17336 * Nested-guest VM-exit handler for control-register accesses (VMX_EXIT_MOV_CRX).
17337 * Conditional VM-exit.
17338 */
17339HMVMX_EXIT_DECL hmR0VmxExitMovCRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17340{
17341 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17342
17343 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17344 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17345 AssertRCReturn(rc, rc);
17346
17347 VBOXSTRICTRC rcStrict;
17348 uint32_t const uAccessType = VMX_EXIT_QUAL_CRX_ACCESS(pVmxTransient->uExitQual);
17349 switch (uAccessType)
17350 {
17351 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:
17352 {
17353 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17354 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17355 Assert(iGReg < RT_ELEMENTS(pVCpu->cpum.GstCtx.aGRegs));
17356 uint64_t const uNewCrX = pVCpu->cpum.GstCtx.aGRegs[iGReg].u64;
17357
17358 bool fIntercept;
17359 switch (iCrReg)
17360 {
17361 case 0:
17362 case 4:
17363 fIntercept = CPUMIsGuestVmxMovToCr0Cr4InterceptSet(pVCpu, &pVCpu->cpum.GstCtx, iCrReg, uNewCrX);
17364 break;
17365
17366 case 3:
17367 fIntercept = CPUMIsGuestVmxMovToCr3InterceptSet(pVCpu, uNewCrX);
17368 break;
17369
17370 case 8:
17371 fIntercept = CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_CR8_LOAD_EXIT);
17372 break;
17373
17374 default:
17375 fIntercept = false;
17376 break;
17377 }
17378 if (fIntercept)
17379 {
17380 VMXVEXITINFO ExitInfo;
17381 RT_ZERO(ExitInfo);
17382 ExitInfo.uReason = pVmxTransient->uExitReason;
17383 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17384 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17385 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17386 }
17387 else
17388 rcStrict = hmR0VmxExitMovToCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17389 break;
17390 }
17391
17392 case VMX_EXIT_QUAL_CRX_ACCESS_READ:
17393 {
17394 /*
17395 * CR0/CR4 reads do not cause VM-exits, the read-shadow is used (subject to masking).
17396 * CR2 reads do not cause a VM-exit.
17397 * CR3 reads cause a VM-exit depending on the "CR3 store exiting" control.
17398 * CR8 reads cause a VM-exit depending on the "CR8 store exiting" control.
17399 */
17400 uint8_t const iCrReg = VMX_EXIT_QUAL_CRX_REGISTER(pVmxTransient->uExitQual);
17401 if ( iCrReg == 3
17402 || iCrReg == 8)
17403 {
17404 static const uint32_t s_auCrXReadIntercepts[] = { 0, 0, 0, VMX_PROC_CTLS_CR3_STORE_EXIT, 0,
17405 0, 0, 0, VMX_PROC_CTLS_CR8_STORE_EXIT };
17406 uint32_t const uIntercept = s_auCrXReadIntercepts[iCrReg];
17407 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, uIntercept))
17408 {
17409 VMXVEXITINFO ExitInfo;
17410 RT_ZERO(ExitInfo);
17411 ExitInfo.uReason = pVmxTransient->uExitReason;
17412 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17413 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17414 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17415 }
17416 else
17417 {
17418 uint8_t const iGReg = VMX_EXIT_QUAL_CRX_GENREG(pVmxTransient->uExitQual);
17419 rcStrict = hmR0VmxExitMovFromCrX(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, iGReg, iCrReg);
17420 }
17421 }
17422 else
17423 {
17424 AssertMsgFailed(("MOV from CR%d VM-exit must not happen\n", iCrReg));
17425 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, iCrReg);
17426 }
17427 break;
17428 }
17429
17430 case VMX_EXIT_QUAL_CRX_ACCESS_CLTS:
17431 {
17432 PCVMXVVMCS pVmcsNstGst = pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pVmcs);
17433 Assert(pVmcsNstGst);
17434 uint64_t const uGstHostMask = pVmcsNstGst->u64Cr0Mask.u;
17435 uint64_t const uReadShadow = pVmcsNstGst->u64Cr0ReadShadow.u;
17436 if ( (uGstHostMask & X86_CR0_TS)
17437 && (uReadShadow & X86_CR0_TS))
17438 {
17439 VMXVEXITINFO ExitInfo;
17440 RT_ZERO(ExitInfo);
17441 ExitInfo.uReason = pVmxTransient->uExitReason;
17442 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17443 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17444 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17445 }
17446 else
17447 rcStrict = hmR0VmxExitClts(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr);
17448 break;
17449 }
17450
17451 case VMX_EXIT_QUAL_CRX_ACCESS_LMSW: /* LMSW (Load Machine-Status Word into CR0) */
17452 {
17453 RTGCPTR GCPtrEffDst;
17454 uint16_t const uNewMsw = VMX_EXIT_QUAL_CRX_LMSW_DATA(pVmxTransient->uExitQual);
17455 bool const fMemOperand = VMX_EXIT_QUAL_CRX_LMSW_OP_MEM(pVmxTransient->uExitQual);
17456 if (fMemOperand)
17457 {
17458 rc = hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17459 AssertRCReturn(rc, rc);
17460 GCPtrEffDst = pVmxTransient->uGuestLinearAddr;
17461 }
17462 else
17463 GCPtrEffDst = NIL_RTGCPTR;
17464
17465 if (CPUMIsGuestVmxLmswInterceptSet(pVCpu, &pVCpu->cpum.GstCtx, uNewMsw))
17466 {
17467 VMXVEXITINFO ExitInfo;
17468 RT_ZERO(ExitInfo);
17469 ExitInfo.uReason = pVmxTransient->uExitReason;
17470 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17471 ExitInfo.u64GuestLinearAddr = GCPtrEffDst;
17472 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17473 rcStrict = IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17474 }
17475 else
17476 rcStrict = hmR0VmxExitLmsw(pVCpu, pVmxTransient->pVmcsInfo, pVmxTransient->cbInstr, uNewMsw, GCPtrEffDst);
17477 break;
17478 }
17479
17480 default:
17481 {
17482 AssertMsgFailed(("Unrecognized Mov CRX access type %#x\n", uAccessType));
17483 HMVMX_UNEXPECTED_EXIT_RET(pVCpu, uAccessType);
17484 }
17485 }
17486
17487 if (rcStrict == VINF_IEM_RAISED_XCPT)
17488 {
17489 ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, HM_CHANGED_RAISED_XCPT_MASK);
17490 rcStrict = VINF_SUCCESS;
17491 }
17492 return rcStrict;
17493}
17494
17495
17496/**
17497 * Nested-guest VM-exit handler for debug-register accesses (VMX_EXIT_MOV_DRX).
17498 * Conditional VM-exit.
17499 */
17500HMVMX_EXIT_DECL hmR0VmxExitMovDRxNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17501{
17502 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17503
17504 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MOV_DR_EXIT))
17505 {
17506 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17507 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17508 AssertRCReturn(rc, rc);
17509
17510 VMXVEXITINFO ExitInfo;
17511 RT_ZERO(ExitInfo);
17512 ExitInfo.uReason = pVmxTransient->uExitReason;
17513 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17514 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17515 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17516 }
17517 return hmR0VmxExitMovDRx(pVCpu, pVmxTransient);
17518}
17519
17520
17521/**
17522 * Nested-guest VM-exit handler for I/O instructions (VMX_EXIT_IO_INSTR).
17523 * Conditional VM-exit.
17524 */
17525HMVMX_EXIT_DECL hmR0VmxExitIoInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17526{
17527 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17528
17529 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17530 AssertRCReturn(rc, rc);
17531
17532 uint32_t const uIOPort = VMX_EXIT_QUAL_IO_PORT(pVmxTransient->uExitQual);
17533 uint8_t const uIOSize = VMX_EXIT_QUAL_IO_SIZE(pVmxTransient->uExitQual);
17534 AssertReturn(uIOSize <= 3 && uIOSize != 2, VERR_VMX_IPE_1);
17535
17536 static uint32_t const s_aIOSizes[4] = { 1, 2, 0, 4 }; /* Size of the I/O accesses in bytes. */
17537 uint8_t const cbAccess = s_aIOSizes[uIOSize];
17538 if (CPUMIsGuestVmxIoInterceptSet(pVCpu, uIOPort, cbAccess))
17539 {
17540 /*
17541 * IN/OUT instruction:
17542 * - Provides VM-exit instruction length.
17543 *
17544 * INS/OUTS instruction:
17545 * - Provides VM-exit instruction length.
17546 * - Provides Guest-linear address.
17547 * - Optionally provides VM-exit instruction info (depends on CPU feature).
17548 */
17549 PVM pVM = pVCpu->CTX_SUFF(pVM);
17550 rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17551 AssertRCReturn(rc, rc);
17552
17553 /* Make sure we don't use stale/uninitialized VMX-transient info. below. */
17554 pVmxTransient->ExitInstrInfo.u = 0;
17555 pVmxTransient->uGuestLinearAddr = 0;
17556
17557 bool const fVmxInsOutsInfo = pVM->cpum.ro.GuestFeatures.fVmxInsOutInfo;
17558 bool const fIOString = VMX_EXIT_QUAL_IO_IS_STRING(pVmxTransient->uExitQual);
17559 if (fIOString)
17560 {
17561 rc |= hmR0VmxReadGuestLinearAddrVmcs(pVCpu, pVmxTransient);
17562 if (fVmxInsOutsInfo)
17563 {
17564 Assert(RT_BF_GET(pVM->hm.s.vmx.Msrs.u64Basic, VMX_BF_BASIC_VMCS_INS_OUTS)); /* Paranoia. */
17565 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17566 }
17567 }
17568 AssertRCReturn(rc, rc);
17569
17570 VMXVEXITINFO ExitInfo;
17571 RT_ZERO(ExitInfo);
17572 ExitInfo.uReason = pVmxTransient->uExitReason;
17573 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17574 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17575 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17576 ExitInfo.u64GuestLinearAddr = pVmxTransient->uGuestLinearAddr;
17577 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17578 }
17579 return hmR0VmxExitIoInstr(pVCpu, pVmxTransient);
17580}
17581
17582
17583/**
17584 * Nested-guest VM-exit handler for RDMSR (VMX_EXIT_RDMSR).
17585 */
17586HMVMX_EXIT_DECL hmR0VmxExitRdmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17587{
17588 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17589
17590 uint32_t fMsrpm;
17591 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17592 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17593 else
17594 fMsrpm = VMXMSRPM_EXIT_RD;
17595
17596 if (fMsrpm & VMXMSRPM_EXIT_RD)
17597 {
17598 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17599 AssertRCReturn(rc, rc);
17600 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17601 }
17602 return hmR0VmxExitRdmsr(pVCpu, pVmxTransient);
17603}
17604
17605
17606/**
17607 * Nested-guest VM-exit handler for WRMSR (VMX_EXIT_WRMSR).
17608 */
17609HMVMX_EXIT_DECL hmR0VmxExitWrmsrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17610{
17611 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17612
17613 uint32_t fMsrpm;
17614 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_MSR_BITMAPS))
17615 fMsrpm = CPUMGetVmxMsrPermission(pVCpu->cpum.GstCtx.hwvirt.vmx.CTX_SUFF(pvMsrBitmap), pVCpu->cpum.GstCtx.ecx);
17616 else
17617 fMsrpm = VMXMSRPM_EXIT_WR;
17618
17619 if (fMsrpm & VMXMSRPM_EXIT_WR)
17620 {
17621 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17622 AssertRCReturn(rc, rc);
17623 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17624 }
17625 return hmR0VmxExitWrmsr(pVCpu, pVmxTransient);
17626}
17627
17628
17629/**
17630 * Nested-guest VM-exit handler for MWAIT (VMX_EXIT_MWAIT). Conditional VM-exit.
17631 */
17632HMVMX_EXIT_DECL hmR0VmxExitMwaitNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17633{
17634 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17635
17636 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MWAIT_EXIT))
17637 {
17638 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17639 AssertRCReturn(rc, rc);
17640 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17641 }
17642 return hmR0VmxExitMwait(pVCpu, pVmxTransient);
17643}
17644
17645
17646/**
17647 * Nested-guest VM-exit handler for monitor-trap-flag (VMX_EXIT_MTF). Conditional
17648 * VM-exit.
17649 */
17650HMVMX_EXIT_DECL hmR0VmxExitMtfNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17651{
17652 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17653
17654 /** @todo NSTVMX: Should consider debugging nested-guests using VM debugger. */
17655 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17656}
17657
17658
17659/**
17660 * Nested-guest VM-exit handler for MONITOR (VMX_EXIT_MONITOR). Conditional VM-exit.
17661 */
17662HMVMX_EXIT_DECL hmR0VmxExitMonitorNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17663{
17664 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17665
17666 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_MONITOR_EXIT))
17667 {
17668 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17669 AssertRCReturn(rc, rc);
17670 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17671 }
17672 return hmR0VmxExitMonitor(pVCpu, pVmxTransient);
17673}
17674
17675
17676/**
17677 * Nested-guest VM-exit handler for PAUSE (VMX_EXIT_PAUSE). Conditional VM-exit.
17678 */
17679HMVMX_EXIT_DECL hmR0VmxExitPauseNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17680{
17681 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17682
17683 /** @todo NSTVMX: Think about this more. Does the outer guest need to intercept
17684 * PAUSE when executing a nested-guest? If it does not, we would not need
17685 * to check for the intercepts here. Just call VM-exit... */
17686
17687 /* The CPU would have already performed the necessary CPL checks for PAUSE-loop exiting. */
17688 if ( CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_PAUSE_EXIT)
17689 || CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_PAUSE_LOOP_EXIT))
17690 {
17691 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17692 AssertRCReturn(rc, rc);
17693 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17694 }
17695 return hmR0VmxExitPause(pVCpu, pVmxTransient);
17696}
17697
17698
17699/**
17700 * Nested-guest VM-exit handler for when the TPR value is lowered below the
17701 * specified threshold (VMX_EXIT_TPR_BELOW_THRESHOLD). Conditional VM-exit.
17702 */
17703HMVMX_EXIT_NSRC_DECL hmR0VmxExitTprBelowThresholdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17704{
17705 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17706
17707 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_USE_TPR_SHADOW))
17708 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, 0 /* uExitQual */);
17709 return hmR0VmxExitTprBelowThreshold(pVCpu, pVmxTransient);
17710}
17711
17712
17713/**
17714 * Nested-guest VM-exit handler for APIC access (VMX_EXIT_APIC_ACCESS). Conditional
17715 * VM-exit.
17716 */
17717HMVMX_EXIT_DECL hmR0VmxExitApicAccessNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17718{
17719 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17720
17721 int rc = hmR0VmxReadExitIntInfoVmcs(pVmxTransient);
17722 rc |= hmR0VmxReadExitIntErrorCodeVmcs(pVmxTransient);
17723 rc |= hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17724 rc |= hmR0VmxReadIdtVectoringInfoVmcs(pVmxTransient);
17725 rc |= hmR0VmxReadIdtVectoringErrorCodeVmcs(pVmxTransient);
17726 AssertRCReturn(rc, rc);
17727
17728 rc = hmR0VmxCheckExitDueToEventDeliveryNested(pVCpu, pVmxTransient);
17729 AssertRCReturn(rc, rc);
17730
17731 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_APIC_ACCESS));
17732 rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17733 AssertRCReturn(rc, rc);
17734
17735 VMXVEXITINFO ExitInfo;
17736 RT_ZERO(ExitInfo);
17737 ExitInfo.uReason = pVmxTransient->uExitReason;
17738 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17739 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17740
17741 VMXVEXITEVENTINFO ExitEventInfo;
17742 RT_ZERO(ExitEventInfo);
17743 ExitEventInfo.uIdtVectoringInfo = pVmxTransient->uIdtVectoringInfo;
17744 ExitEventInfo.uIdtVectoringErrCode = pVmxTransient->uIdtVectoringErrorCode;
17745 if (pVCpu->hm.s.Event.fPending)
17746 {
17747 Assert(ExitEventInfo.uIdtVectoringInfo == pVCpu->hm.s.Event.u64IntInfo);
17748 Assert(ExitEventInfo.uIdtVectoringErrCode == pVCpu->hm.s.Event.u32ErrCode);
17749 pVCpu->hm.s.Event.fPending = false;
17750 }
17751 return IEMExecVmxVmexitApicAccess(pVCpu, &ExitInfo, &ExitEventInfo);
17752}
17753
17754
17755/**
17756 * Nested-guest VM-exit handler for APIC write emulation (VMX_EXIT_APIC_WRITE).
17757 * Conditional VM-exit.
17758 */
17759HMVMX_EXIT_DECL hmR0VmxExitApicWriteNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17760{
17761 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17762
17763 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_APIC_REG_VIRT));
17764 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17765 AssertRCReturn(rc, rc);
17766
17767 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17768}
17769
17770
17771/**
17772 * Nested-guest VM-exit handler for virtualized EOI (VMX_EXIT_VIRTUALIZED_EOI).
17773 * Conditional VM-exit.
17774 */
17775HMVMX_EXIT_DECL hmR0VmxExitVirtEoiNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17776{
17777 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17778
17779 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_VIRT_INT_DELIVERY));
17780 int rc = hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17781 AssertRCReturn(rc, rc);
17782
17783 return IEMExecVmxVmexit(pVCpu, pVmxTransient->uExitReason, pVmxTransient->uExitQual);
17784}
17785
17786
17787/**
17788 * Nested-guest VM-exit handler for RDTSCP (VMX_EXIT_RDTSCP). Conditional VM-exit.
17789 */
17790HMVMX_EXIT_DECL hmR0VmxExitRdtscpNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17791{
17792 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17793
17794 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_RDTSC_EXIT))
17795 {
17796 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_RDTSCP));
17797 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17798 AssertRCReturn(rc, rc);
17799 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17800 }
17801 return hmR0VmxExitRdtscp(pVCpu, pVmxTransient);
17802}
17803
17804
17805/**
17806 * Nested-guest VM-exit handler for WBINVD (VMX_EXIT_WBINVD). Conditional VM-exit.
17807 */
17808HMVMX_EXIT_NSRC_DECL hmR0VmxExitWbinvdNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17809{
17810 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17811
17812 if (CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_WBINVD_EXIT))
17813 {
17814 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17815 AssertRCReturn(rc, rc);
17816 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17817 }
17818 return hmR0VmxExitWbinvd(pVCpu, pVmxTransient);
17819}
17820
17821
17822/**
17823 * Nested-guest VM-exit handler for INVPCID (VMX_EXIT_INVPCID). Conditional VM-exit.
17824 */
17825HMVMX_EXIT_DECL hmR0VmxExitInvpcidNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17826{
17827 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17828
17829 if (CPUMIsGuestVmxProcCtlsSet(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS_INVLPG_EXIT))
17830 {
17831 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, &pVCpu->cpum.GstCtx, VMX_PROC_CTLS2_INVPCID));
17832 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17833 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17834 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17835 AssertRCReturn(rc, rc);
17836
17837 VMXVEXITINFO ExitInfo;
17838 RT_ZERO(ExitInfo);
17839 ExitInfo.uReason = pVmxTransient->uExitReason;
17840 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17841 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17842 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17843 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17844 }
17845 return hmR0VmxExitInvpcid(pVCpu, pVmxTransient);
17846}
17847
17848
17849/**
17850 * Nested-guest VM-exit handler for invalid-guest state
17851 * (VMX_EXIT_ERR_INVALID_GUEST_STATE). Error VM-exit.
17852 */
17853HMVMX_EXIT_DECL hmR0VmxExitErrInvalidGuestStateNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17854{
17855 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17856
17857 /*
17858 * Currently this should never happen because we fully emulate VMLAUNCH/VMRESUME in IEM.
17859 * So if it does happen, it indicates a bug possibly in the hardware-assisted VMX code.
17860 * Handle it like it's in an invalid guest state of the outer guest.
17861 *
17862 * When the fast path is implemented, this should be changed to cause the corresponding
17863 * nested-guest VM-exit.
17864 */
17865 return hmR0VmxExitErrInvalidGuestState(pVCpu, pVmxTransient);
17866}
17867
17868
17869/**
17870 * Nested-guest VM-exit handler for instructions that cause VM-exits uncondtionally
17871 * and only provide the instruction length.
17872 *
17873 * Unconditional VM-exit.
17874 */
17875HMVMX_EXIT_DECL hmR0VmxExitInstrNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17876{
17877 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17878
17879#ifdef VBOX_STRICT
17880 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17881 switch (pVmxTransient->uExitReason)
17882 {
17883 case VMX_EXIT_ENCLS:
17884 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_ENCLS_EXIT));
17885 break;
17886
17887 case VMX_EXIT_VMFUNC:
17888 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_VMFUNC));
17889 break;
17890 }
17891#endif
17892
17893 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17894 AssertRCReturn(rc, rc);
17895 return IEMExecVmxVmexitInstr(pVCpu, pVmxTransient->uExitReason, pVmxTransient->cbInstr);
17896}
17897
17898
17899/**
17900 * Nested-guest VM-exit handler for instructions that provide instruction length as
17901 * well as more information.
17902 *
17903 * Unconditional VM-exit.
17904 */
17905HMVMX_EXIT_DECL hmR0VmxExitInstrWithInfoNested(PVMCPU pVCpu, PVMXTRANSIENT pVmxTransient)
17906{
17907 HMVMX_VALIDATE_NESTED_EXIT_HANDLER_PARAMS(pVCpu, pVmxTransient);
17908
17909#ifdef VBOX_STRICT
17910 PCCPUMCTX pCtx = &pVCpu->cpum.GstCtx;
17911 switch (pVmxTransient->uExitReason)
17912 {
17913 case VMX_EXIT_GDTR_IDTR_ACCESS:
17914 case VMX_EXIT_LDTR_TR_ACCESS:
17915 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_DESC_TABLE_EXIT));
17916 break;
17917
17918 case VMX_EXIT_RDRAND:
17919 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDRAND_EXIT));
17920 break;
17921
17922 case VMX_EXIT_RDSEED:
17923 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_RDSEED_EXIT));
17924 break;
17925
17926 case VMX_EXIT_XSAVES:
17927 case VMX_EXIT_XRSTORS:
17928 /** @todo NSTVMX: Verify XSS-bitmap. */
17929 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_XSAVES_XRSTORS));
17930 break;
17931
17932 case VMX_EXIT_UMWAIT:
17933 case VMX_EXIT_TPAUSE:
17934 Assert(CPUMIsGuestVmxProcCtlsSet(pVCpu, pCtx, VMX_PROC_CTLS_RDTSC_EXIT));
17935 Assert(CPUMIsGuestVmxProcCtls2Set(pVCpu, pCtx, VMX_PROC_CTLS2_USER_WAIT_PAUSE));
17936 break;
17937 }
17938#endif
17939
17940 int rc = hmR0VmxReadExitInstrLenVmcs(pVmxTransient);
17941 rc |= hmR0VmxReadExitQualVmcs(pVCpu, pVmxTransient);
17942 rc |= hmR0VmxReadExitInstrInfoVmcs(pVmxTransient);
17943 AssertRCReturn(rc, rc);
17944
17945 VMXVEXITINFO ExitInfo;
17946 RT_ZERO(ExitInfo);
17947 ExitInfo.uReason = pVmxTransient->uExitReason;
17948 ExitInfo.cbInstr = pVmxTransient->cbInstr;
17949 ExitInfo.u64Qual = pVmxTransient->uExitQual;
17950 ExitInfo.InstrInfo = pVmxTransient->ExitInstrInfo;
17951 return IEMExecVmxVmexitInstrWithInfo(pVCpu, &ExitInfo);
17952}
17953
17954/** @} */
17955#endif /* VBOX_WITH_NESTED_HWVIRT_VMX */
17956
Note: See TracBrowser for help on using the repository browser.

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